OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / user / dhcpcd / main.c
1 /* $Id: main.c,v 1.15 2002-03-07 02:29:14 gerg Exp $
2  *
3  * dhcpcd - DHCP client daemon -
4  * Copyright (C) 1996 - 1997 Yoichi Hariguchi <yoichi@fore.com>
5  *
6  * dhcpcd is an RFC2131 and RFC1541 compliant DHCP client daemon.
7  *
8  * This is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  * See the GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <errno.h>
28 #include <string.h>
29 #include <syslog.h>
30 #include <time.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33 #include <net/if.h>
34 #include <arpa/inet.h>
35 #include "if.h"
36 #include "dhcp.h"
37 #include "signal-handler.h"
38 #include "error-handler.h"
39 #include "daemon.h"
40 #include "client.h"
41 #include "memory.h"
42
43 #define DEFAULT_IF      "eth0"
44
45 char *CommandFile = NULL;               /* invoked command file name when dhcpcd
46                                                                  * succeeds in getting an IP address
47                                                                  */
48 int       BeRFC1541 = 0;                        /* default is InternetDraft mode */
49 char *Hostname = NULL;                  /* hostname in the DHCP msg for xmit */
50 int   Persistent = 0;                   /* Keep trying until you get address */
51 int   ArpCheck = 1;                             /* Check if address already used? */
52
53 #ifdef LLIP_SUPPORT
54 #include "llip.h"
55 int     AutoIP  = 0;
56 #endif
57
58 char  pidfile[128];                     /* file name in which pid is stored */
59 static char VersionStr[] = "dhcpcd 0.70\n";
60
61 void    usage();
62
63 char  Ifname[16];                       /* global interface name */
64
65
66 int
67 main(argc, argv)
68 int argc;
69 char *argv[];
70 {
71         char  ifname[16];                       /* interface name */
72         char *clientId = NULL;          /* ptr to client identifier user specified */
73         int   killFlag = 0;                     /* if 1: kill the running proc and exit */
74
75         int res;
76         DebugFlag = 0;                          /* default is NON debug mode */
77         srand((u_int)time(NULL));
78         signalSetup();
79         umask(0);                                       /* clear umask */
80         classIDsetup(NULL);                     /* setup default class identifier */
81         /* option handling
82          */
83         while ( *++argv ) {
84                 if ( **argv == '-' ) {
85                         switch ( argv[0][1] ) {
86                           case 'c':
87                                 if ( *++argv == NULL ) {
88                                         usage();
89                                 }
90                                 if ( (CommandFile = malloc(strlen(*argv)+1)) == NULL ) {
91                                         usage();
92                                 }
93                                 strcpy(CommandFile, *argv);
94                                 break;
95                           case 'd':
96                                 DebugFlag = 1;
97                                 break;
98                           case 'p':
99                                 Persistent = 1;
100                                 break;
101                           case 'a':
102                                 ArpCheck = 0;
103                                 break;
104                           case 'h':
105                                 if ( *++argv == NULL ) {
106                                         usage();
107                                 }
108                                 Hostname = smalloc(strlen(*argv)+1);
109                                 strcpy(Hostname, *argv);
110                                 break;
111                           case 'i':
112                                 if ( *++argv == NULL ) {
113                                         usage();
114                                 }
115                                 classIDsetup(*argv); /* overwrite class identifier */
116                                 break;
117                           case 'I':
118                                 if ( *++argv == NULL ) {
119                                         usage();
120                                 }
121                                 clientId = *argv;
122                                 break;
123                           case 'k':
124                                 killFlag = 1;   /* kill running process and exit */
125                                 break;
126                           case 'l':
127                                 ++argv;
128                                 if ( *argv == NULL || **argv == '-' ) {
129                                         usage();
130                                 }
131                                 SuggestLeaseTime = atol(*argv);
132                                 break;
133                           case 'r':
134                                 BeRFC1541 = 1;  /* Be RFC1541 compliant */
135                                 break;
136                           case 'v':
137                                 fflush(stdout);
138                                 fputs(VersionStr, stderr);
139                                 fflush(NULL);
140                                 exit(0);
141 #ifdef LLIP_SUPPORT
142                         case 'A': /* auto IP support if no dhcp lease is obtained */
143                                 AutoIP=1;
144                                 Persistent=1;
145                                 break;
146 #else
147                         case 'A': /* auto IP support option is ignored but logged */
148                                 syslog(LOG_WARNING, "-A (enable auto IP) option was specified but will be ignored.");
149                                 break;
150 #endif
151                           default:
152                                 usage();
153                         }
154                 } else {
155                         break;
156                 }
157         }
158
159         if ( getuid() != 0 && geteuid() != 0 ) {
160                 errQuit("Must be root");
161         }
162         if ( *argv ) {
163                 strncpy(ifname, *argv, sizeof(ifname));
164         } else {
165                 strncpy(ifname, DEFAULT_IF, sizeof(ifname));
166         }
167 #ifndef EMBED
168         /*
169          * Don't do this for now...
170          */
171         if ( killFlag ) {
172                 sprintf(pidfile, PIDFILE, ifname);
173                 killCurProc(pidfile);
174         }
175         if ( !DebugFlag ) {
176                 sprintf(pidfile, PIDFILE, ifname);
177                 daemonInit(pidfile);
178         }
179 #endif
180         sleep(1);
181         logOpen("dhcpcd", LOG_PID, LOG_LOCAL0);
182         ifReset(ifname);                        /* reset interface, 'Ifbuf' */
183         clientIDsetup(clientId, ifname);
184         dhcpMsgInit(ifname);
185         dhcpClient();
186         exit(0);
187 }
188
189 void
190 usage()
191 {
192         fflush(stdout);
193 #ifndef LLIP_SUPPORT
194         fputs("Usage: dhcpcd [-c filename] [-dpa] [-i classIdentifier] [-I clientIdentifier] [-k] [-l leasetime] [-h hostname] [ifname]\n",
195                   stderr);
196 #else
197         fputs("Usage: dhcpcd [-c filename] [-dpaA] [-i classIdentifier] [-I clientIdentifier] [-k] [-l leasetime] [-h hostname] [ifname]\n", stderr);
198 #endif
199         fflush(NULL);
200         exit(1);
201 }
202
203 void die(int rc)
204 {
205 /*
206  * Kill the pid file.
207  */
208         unlink(pidfile);
209         exit(rc);
210 }
211
212 /*
213  * Write out the pid into the file specified by pidfile.
214  * return code:    0   - everything worked like a dream
215  *                 1   - there was a stale PID file
216  *                -1   - something went wrong
217  *                -2   - the program is already running
218  */ 
219 int writePidFile()
220 {
221         FILE    *file;
222         pid_t   pid;
223         int     fd, rc, old = 0;
224
225         pid = getpid();
226         fd = open(pidfile, O_CREAT | O_EXCL | O_RDWR, S_IRWXU);
227         if (fd < 0) {
228                 if (errno == EEXIST) {
229                         /* See if the old program is still alive */
230                         if ((rc = isOldPid()) < 0) {
231                                 return(-1);
232                         } else if (rc == 1) {
233                                 old = 1;
234                         }else {
235                                 return(-2);
236                         }
237                 } else {
238                         fprintf(stderr, "DHCPCD: unexpected errno value"
239                                 " - %d\n", errno);
240                         return(-1);
241                 }
242         }
243         close(fd);
244
245         if ((file = fopen(pidfile, "w")) == NULL) {
246                 fprintf(stderr, "DHCPCD: open pid file errno=%d\n", errno);
247                 return(-1);
248         }
249         rc = fprintf(file, "%d\n",  pid);
250         fclose(file);
251
252         if (rc <= 0) {
253                 fprintf(stderr, "DHCPCD: pif file errno=%d\n", errno);
254                 return(-1);
255         }
256
257         return(old);
258 }
259
260
261 /*
262  * Check whether a pidfile contains the pid for a current active dhcpcd, or an
263  * old defunct one (which would hang around in the case of a -9)
264  * return code:   1  - the pidfile is NOT a currently active dhcpcd
265  *                0  - the pidfile is a currently active dhcpcd
266  */
267 int isOldPid()
268 {
269         FILE    *file;
270         char    fileName[48];
271         char    oldCmd[7] = {'\0'};
272         pid_t   pid;
273         int     rc;
274
275         if ((file = fopen(pidfile, "r")) == NULL)
276                 return(-1);
277         rc = fscanf(file, "%d", &pid);
278         fclose(file);
279
280         if (rc <= 0)
281                 return(-1);
282
283         sprintf(fileName, "/proc/%d/cmdline", pid);
284         if ((file = fopen(fileName, "r")) == NULL)
285                 return(1);
286         rc = fread(oldCmd, sizeof(oldCmd) - 1, 1, file);
287         fclose(file);
288
289         if (rc != 1)
290                 return(1);
291
292         oldCmd[6] = '\0';
293         if(strcmp("dhcpcd", oldCmd) == 0)
294                 return(0);
295         return(1);
296 }