]> git.ozlabs.org Git - ppp.git/blob - pppd/plugins/pppoe/pppoe-discovery.c
Cleanup in pppd/pppd.h, eliminate unecessary headers
[ppp.git] / pppd / plugins / pppoe / pppoe-discovery.c
1 /*
2  * Perform PPPoE discovery
3  *
4  * Copyright (C) 2000-2001 by Roaring Penguin Software Inc.
5  * Copyright (C) 2004 Marco d'Itri <md@linux.it>
6  *
7  * This program may be distributed according to the terms of the GNU
8  * General Public License, version 2 or (at your option) any later version.
9  *
10  */
11
12 #ifdef HAVE_CONFIG_H
13 #include "config.h"
14 #endif
15
16 #include <stdarg.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <errno.h>
21 #include <string.h>
22 #include <time.h>
23 #include <signal.h>
24 #include <sys/time.h>
25
26 #include "pppoe.h"
27
28 int debug;
29 int got_sigterm;
30 int pppoe_verbose;
31 static FILE *debugFile;
32
33 void
34 fatal(char *fmt, ...)
35 {
36     va_list pvar;
37     va_start(pvar, fmt);
38     vfprintf(stderr, fmt, pvar);
39     va_end(pvar);
40     fputc('\n', stderr);
41     exit(1);
42 }
43
44 void
45 error(char *fmt, ...)
46 {
47     va_list pvar;
48     va_start(pvar, fmt);
49     vfprintf(stderr, fmt, pvar);
50     fputc('\n', stderr);
51     va_end(pvar);
52 }
53
54 void
55 warn(char *fmt, ...)
56 {
57     va_list pvar;
58     va_start(pvar, fmt);
59     vfprintf(stderr, fmt, pvar);
60     fputc('\n', stderr);
61     va_end(pvar);
62 }
63
64 void
65 info(char *fmt, ...)
66 {
67     va_list pvar;
68     va_start(pvar, fmt);
69     vprintf(fmt, pvar);
70     putchar('\n');
71     va_end(pvar);
72 }
73
74 void
75 init_pr_log(const char *prefix, int level)
76 {
77 }
78
79 void
80 end_pr_log(void)
81 {
82     fflush(debugFile);
83 }
84
85 void
86 pr_log(void *arg, char *fmt, ...)
87 {
88     va_list ap;
89     va_start(ap, fmt);
90     vfprintf(debugFile, fmt, ap);
91     va_end(ap);
92 }
93
94 size_t
95 strlcpy(char *dest, const char *src, size_t len)
96 {
97     size_t ret = strlen(src);
98
99     if (len != 0) {
100         if (ret < len)
101             strcpy(dest, src);
102         else {
103             strncpy(dest, src, len - 1);
104             dest[len-1] = 0;
105         }
106     }
107     return ret;
108 }
109
110 static char *
111 xstrdup(const char *s)
112 {
113     char *ret = strdup(s);
114     if (!ret) {
115         perror("strdup");
116         exit(1);
117     }
118     return ret;
119 }
120
121 int
122 get_time(struct timeval *tv)
123 {
124     return gettimeofday(tv, NULL);
125 }
126
127 static void
128 term_handler(int signum)
129 {
130     got_sigterm = 1;
131 }
132
133 static void usage(void);
134
135 int main(int argc, char *argv[])
136 {
137     int opt;
138     PPPoEConnection *conn;
139
140     signal(SIGINT, term_handler);
141     signal(SIGTERM, term_handler);
142
143     conn = malloc(sizeof(PPPoEConnection));
144     if (!conn) {
145         perror("malloc");
146         exit(1);
147     }
148
149     memset(conn, 0, sizeof(PPPoEConnection));
150
151     pppoe_verbose = 1;
152     conn->discoveryTimeout = PADI_TIMEOUT;
153     conn->discoveryAttempts = MAX_PADI_ATTEMPTS;
154
155     while ((opt = getopt(argc, argv, "I:D:VUQS:C:W:t:a:h")) > 0) {
156         switch(opt) {
157         case 'S':
158             conn->serviceName = xstrdup(optarg);
159             break;
160         case 'C':
161             conn->acName = xstrdup(optarg);
162             break;
163         case 't':
164             if (sscanf(optarg, "%d", &conn->discoveryTimeout) != 1) {
165                 fprintf(stderr, "Illegal argument to -t: Should be -t timeout\n");
166                 exit(EXIT_FAILURE);
167             }
168             if (conn->discoveryTimeout < 1) {
169                 conn->discoveryTimeout = 1;
170             }
171             break;
172         case 'a':
173             if (sscanf(optarg, "%d", &conn->discoveryAttempts) != 1) {
174                 fprintf(stderr, "Illegal argument to -a: Should be -a attempts\n");
175                 exit(EXIT_FAILURE);
176             }
177             if (conn->discoveryAttempts < 1) {
178                 conn->discoveryAttempts = 1;
179             }
180             break;
181         case 'U':
182             if(conn->hostUniq.length) {
183                 fprintf(stderr, "-U and -W are mutually exclusive\n");
184                 exit(EXIT_FAILURE);
185             } else {
186                 pid_t pid = getpid();
187                 conn->hostUniq.type = htons(TAG_HOST_UNIQ);
188                 conn->hostUniq.length = htons(sizeof(pid));
189                 memcpy(conn->hostUniq.payload, &pid, sizeof(pid));
190             }
191             break;
192         case 'W':
193             if(conn->hostUniq.length) {
194                 fprintf(stderr, "-U and -W are mutually exclusive\n");
195                 exit(EXIT_FAILURE);
196             }
197             if (!parseHostUniq(optarg, &conn->hostUniq)) {
198                 fprintf(stderr, "Invalid host-uniq argument: %s\n", optarg);
199                 exit(EXIT_FAILURE);
200             }
201             break;
202         case 'D':
203             pppoe_verbose = 2;
204             debug = 1;
205             debugFile = fopen(optarg, "w");
206             if (!debugFile) {
207                 fprintf(stderr, "Could not open %s: %s\n",
208                         optarg, strerror(errno));
209                 exit(1);
210             }
211             fprintf(debugFile, "pppoe-discovery from pppd %s\n", PPPD_VERSION);
212             break;
213         case 'I':
214             conn->ifName = xstrdup(optarg);
215             break;
216         case 'Q':
217             pppoe_verbose = 0;
218             break;
219         case 'V':
220         case 'h':
221             usage();
222             exit(0);
223         default:
224             usage();
225             exit(1);
226         }
227     }
228
229     if (optind != argc) {
230         fprintf(stderr, "%s: extra argument '%s'\n", argv[0], argv[optind]);
231         usage();
232         exit(EXIT_FAILURE);
233     }
234
235     if (!conn->ifName) {
236         fprintf(stderr, "Interface was not specified\n");
237         exit(EXIT_FAILURE);
238     }
239
240     conn->sessionSocket = -1;
241
242     conn->discoverySocket = openInterface(conn->ifName, Eth_PPPOE_Discovery, conn->myEth);
243     if (conn->discoverySocket < 0) {
244         perror("Cannot create PPPoE discovery socket");
245         exit(1);
246     }
247
248     discovery1(conn);
249
250     if (!conn->numPADOs)
251         exit(1);
252     else
253         exit(0);
254 }
255
256 static void
257 usage(void)
258 {
259     fprintf(stderr, "Usage: pppoe-discovery [options]\n");
260     fprintf(stderr, "Options:\n");
261     fprintf(stderr, "   -I if_name     -- Specify interface (mandatory option)\n");
262     fprintf(stderr, "   -D filename    -- Log debugging information in filename.\n");
263     fprintf(stderr,
264             "   -t timeout     -- Initial timeout for discovery packets in seconds\n"
265             "   -a attempts    -- Number of discovery attempts\n"
266             "   -V             -- Print version and exit.\n"
267             "   -Q             -- Quit Mode: Do not print access concentrator names\n"
268             "   -S name        -- Set desired service name.\n"
269             "   -C name        -- Set desired access concentrator name.\n"
270             "   -U             -- Use Host-Unique to allow multiple PPPoE sessions.\n"
271             "   -W hexvalue    -- Set the Host-Unique to the supplied hex string.\n"
272             "   -h             -- Print usage information.\n");
273     fprintf(stderr, "\npppoe-discovery from pppd " PPPD_VERSION "\n");
274 }