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