1 /***********************************************************************
2 *
3 * if.c
4 *
5 * Implementation of user-space PPPoE redirector for Linux.
6 *
7 * Functions for opening a raw socket and reading/writing raw Ethernet frames.
8 *
9 * Copyright (C) 2000-2012 by Roaring Penguin Software Inc.
10 * Copyright (C) 2018-2021 Dianne Skoll
11 *
12 * This program may be distributed according to the terms of the GNU
13 * General Public License, version 2 or (at your option) any later version.
14 *
15 * LIC: GPL
16 *
17 ***********************************************************************/
18 
19 #include "pppoe.h"
20 #if defined(HAVE_LINUX_IF_H)
21 #include <linux/if.h>
22 #elif defined(HAVE_NET_IF_H)
23 #include <net/if.h>
24 #endif
25 
26 #ifdef HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
29 
30 #ifdef HAVE_NETPACKET_PACKET_H
31 #include <netpacket/packet.h>
32 #elif defined(HAVE_LINUX_IF_PACKET_H)
33 #include <linux/if_packet.h>
34 #endif
35 
36 #ifdef HAVE_NET_ETHERNET_H
37 #include <net/ethernet.h>
38 #endif
39 
40 #ifdef HAVE_ASM_TYPES_H
41 #include <asm/types.h>
42 #endif
43 
44 #ifdef HAVE_SYS_IOCTL_H
45 #include <sys/ioctl.h>
46 #endif
47 
48 #ifdef HAVE_SYSLOG_H
49 #include <syslog.h>
50 #endif
51 
52 #include <errno.h>
53 #include <stdlib.h>
54 #include <string.h>
55 
56 #ifdef HAVE_NET_IF_ARP_H
57 #include <net/if_arp.h>
58 #endif
59 
60 #ifdef USE_DLPI
61 
62 #include <limits.h>
63 #include <fcntl.h>
64 #include <stdlib.h>
65 #include <sys/types.h>
66 #include <sys/time.h>
67 #include <sys/stream.h>
68 #include <sys/stropts.h>
69 #include <sys/dlpi.h>
70 #include <sys/bufmod.h>
71 #include <stdio.h>
72 #include <signal.h>
73 #include <stropts.h>
74 
75 /* function declarations */
76 
77 static void dlpromisconreq( int fd, u_long  level);
78 void dlinforeq(int fd);
79 void dlunitdatareq(int fd, u_char *addrp, int addrlen, u_long minpri, u_long maxpri, u_char *datap, int datalen);
80 void dlinfoack(int fd, char *bufp);
81 void dlbindreq(int fd, u_long sap, u_long max_conind, u_long service_mode, u_long conn_mgmt, u_long xidtest);
82 void dlattachreq(int fd, u_long ppa);
83 void dlokack(int fd, char *bufp);
84 void dlbindack(int fd, char *bufp);
85 int strioctl(int fd, int cmd, int timout, int len, char *dp);
86 void strgetmsg(int fd, struct strbuf *ctlp, struct strbuf *datap, int *flagsp, char *caller);
87 void sigalrm(int sig);
88 void expecting(int prim, union DL_primitives *dlp);
89 static char *dlprim(u_long prim);
90 
91 /* #define DL_DEBUG */
92 
93 static	int     dl_abssaplen;
94 static	int     dl_saplen;
95 static	int	dl_addrlen;
96 
97 #endif
98 
99 #ifdef USE_BPF
100 #include <net/bpf.h>
101 #include <fcntl.h>
102 
103 static unsigned char *bpfBuffer;	/* Packet filter buffer */
104 static int bpfLength = 0;		/* Packet filter buffer length */
105        int bpfSize = 0;		        /* Number of unread bytes in buffer */
106 static int bpfOffset = 0;		/* Current offset in bpfBuffer */
107 #endif
108 
109 /* Initialize frame types to RFC 2516 values.  Some broken peers apparently
110    use different frame types... sigh... */
111 
112 UINT16_t Eth_PPPOE_Discovery = ETH_PPPOE_DISCOVERY;
113 UINT16_t Eth_PPPOE_Session   = ETH_PPPOE_SESSION;
114 
115 /**********************************************************************
116 *%FUNCTION: etherType
117 *%ARGUMENTS:
118 * packet -- a received PPPoE packet
119 *%RETURNS:
120 * ethernet packet type (see /usr/include/net/ethertypes.h)
121 *%DESCRIPTION:
122 * Checks the ethernet packet header to determine its type.
123 * We should only be receveing DISCOVERY and SESSION types if the BPF
124 * is set up correctly.  Logs an error if an unexpected type is received.
125 * Note that the ethernet type names come from "pppoe.h" and the packet
126 * packet structure names use the LINUX dialect to maintain consistency
127 * with the rest of this file.  See the BSD section of "pppoe.h" for
128 * translations of the data structure names.
129 ***********************************************************************/
130 UINT16_t
etherType(PPPoEPacket * packet)131 etherType(PPPoEPacket *packet)
132 {
133     UINT16_t type = (UINT16_t) ntohs(packet->ethHdr.h_proto);
134     if (type != Eth_PPPOE_Discovery && type != Eth_PPPOE_Session) {
135 	syslog(LOG_ERR, "Invalid ether type 0x%x", type);
136     }
137     return type;
138 }
139 
140 #ifdef USE_BPF
141 /**********************************************************************
142 *%FUNCTION: getHWaddr
143 *%ARGUMENTS:
144 * ifname -- name of interface
145 * hwaddr -- buffer for ehthernet address
146 *%RETURNS:
147 * Nothing
148 *%DESCRIPTION:
149 * Locates the Ethernet hardware address for an interface.
150 ***********************************************************************/
151 void
getHWaddr(int sock,char const * ifname,unsigned char * hwaddr)152 getHWaddr(int sock, char const *ifname, unsigned char *hwaddr)
153 {
154     char inbuf[8192];
155     const struct sockaddr_dl *sdl;
156     struct ifconf ifc;
157     struct ifreq ifreq, *ifr;
158     int i;
159     int found = 0;
160 
161     ifc.ifc_len = sizeof(inbuf);
162     ifc.ifc_buf = inbuf;
163     if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
164 	fatalSys("SIOCGIFCONF");
165     }
166     ifr = ifc.ifc_req;
167     ifreq.ifr_name[0] = '\0';
168     for (i = 0; i < ifc.ifc_len; ) {
169 	ifr = (struct ifreq *)((caddr_t)ifc.ifc_req + i);
170 	i += sizeof(ifr->ifr_name) +
171 		    (ifr->ifr_addr.sa_len > sizeof(struct sockaddr)
172 		    ? ifr->ifr_addr.sa_len
173 		    : sizeof(struct sockaddr));
174 	if (ifr->ifr_addr.sa_family == AF_LINK) {
175 	    sdl = (const struct sockaddr_dl *) &ifr->ifr_addr;
176 	    if ((sdl->sdl_type == IFT_ETHER) &&
177 		(sdl->sdl_alen == ETH_ALEN) &&
178 		!strncmp(ifname, ifr->ifr_name, sizeof(ifr->ifr_name))) {
179 		if (found) {
180 		    char buffer[256];
181 		    sprintf(buffer, "interface %.16s has more than one ethernet address", ifname);
182 		    rp_fatal(buffer);
183 		} else {
184 		    found = 1;
185 		    memcpy(hwaddr, LLADDR(sdl), ETH_ALEN);
186 		}
187 	    }
188 	}
189     }
190     if (!found) {
191 	char buffer[256];
192 	sprintf(buffer, "interface %.16s has no ethernet address", ifname);
193 	rp_fatal(buffer);
194     }
195 }
196 
197 /**********************************************************************
198 *%FUNCTION: initFilter
199 *%ARGUMENTS:
200 * fd -- file descriptor of BSD device
201 * type -- Ethernet frame type (0 for watch mode)
202 * hwaddr -- buffer with ehthernet address
203 *%RETURNS:
204 * Nothing
205 *%DESCRIPTION:
206 * Initializes the packet filter rules.
207 ***********************************************************************/
208 void
initFilter(int fd,UINT16_t type,unsigned char * hwaddr)209 initFilter(int fd, UINT16_t type, unsigned char *hwaddr)
210 {
211     /* Packet Filter Instructions:
212      * Note that the ethernet type names come from "pppoe.h" and are
213      * used here to maintain consistency with the rest of this file. */
214     static struct bpf_insn bpfRun[] = {         /* run PPPoE */
215 	BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12),     /* ethernet type */
216 	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETH_PPPOE_SESSION, 5, 0),
217 	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETH_PPPOE_DISCOVERY, 0, 9),
218 	BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 0),      /* first word of dest. addr */
219 #define PPPOE_BCAST_CMPW 4                     /* offset of word compare */
220 	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 2),
221 	BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 4),      /* next 1/2 word of dest. */
222 #define PPPOE_BCAST_CMPH 6                     /* offset of 1/2 word compare */
223 	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 4, 0),
224 	BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 0),      /* first word of dest. addr */
225 #define PPPOE_FILTER_CMPW 8                     /* offset of word compare */
226 	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 3),
227 	BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 4),      /* next 1/2 word of dest. */
228 #define PPPOE_FILTER_CMPH 10                    /* offset of 1/rd compare */
229 	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 1),
230 	BPF_STMT(BPF_RET+BPF_K, (u_int) -1),    /* keep packet */
231 	BPF_STMT(BPF_RET+BPF_K, 0),             /* drop packet */
232     };
233 
234     /* Fix the potentially varying parts */
235     bpfRun[1].code = (u_short) BPF_JMP+BPF_JEQ+BPF_K;
236     bpfRun[1].jt   = 5;
237     bpfRun[1].jf   = 0;
238     bpfRun[1].k    = Eth_PPPOE_Session;
239 
240     bpfRun[2].code = (u_short) BPF_JMP+BPF_JEQ+BPF_K;
241     bpfRun[2].jt   = 0;
242     bpfRun[2].jf   = 9;
243     bpfRun[2].k    = Eth_PPPOE_Discovery;
244 
245     {
246       struct bpf_insn bpfInsn[sizeof(bpfRun) / sizeof(bpfRun[0])];
247       struct bpf_program bpfProgram;
248       memcpy(bpfInsn, bpfRun, sizeof(bpfRun));
249       bpfInsn[PPPOE_BCAST_CMPW].k = ((0xff << 24) | (0xff << 16) |
250 				     (0xff << 8) | 0xff);
251       bpfInsn[PPPOE_BCAST_CMPH].k = ((0xff << 8) | 0xff);
252       bpfInsn[PPPOE_FILTER_CMPW].k = ((hwaddr[0] << 24) | (hwaddr[1] << 16) |
253 				      (hwaddr[2] << 8) | hwaddr[3]);
254       bpfInsn[PPPOE_FILTER_CMPH].k = ((hwaddr[4] << 8) | hwaddr[5]);
255       bpfProgram.bf_len = (sizeof(bpfInsn) / sizeof(bpfInsn[0]));
256       bpfProgram.bf_insns = &bpfInsn[0];
257 
258       /* Apply the filter */
259       if (ioctl(fd, BIOCSETF, &bpfProgram) < 0) {
260 	fatalSys("ioctl(BIOCSETF)");
261       }
262     }
263 }
264 
265 /**********************************************************************
266 *%FUNCTION: openInterface
267 *%ARGUMENTS:
268 * ifname -- name of interface
269 * type -- Ethernet frame type (0 for any frame type)
270 * hwaddr -- if non-NULL, set to the hardware address
271 *%RETURNS:
272 * A file descriptor for talking with the Ethernet card.  Exits on error.
273 * Note that the Linux version of this routine returns a socket instead.
274 *%DESCRIPTION:
275 * Opens a BPF on an interface for all PPPoE traffic (discovery and
276 * session).  If 'type' is 0, uses promiscuous mode to watch any PPPoE
277 * traffic on this network.
278 ***********************************************************************/
279 int
openInterface(char const * ifname,UINT16_t type,unsigned char * hwaddr,UINT16_t * mtu)280 openInterface(char const *ifname, UINT16_t type, unsigned char *hwaddr, UINT16_t *mtu)
281 {
282     static int fd = -1;
283     char bpfName[32];
284     u_int optval;
285     struct bpf_version bpf_ver;
286     struct ifreq ifr;
287     int sock;
288     int i;
289 
290     /* BSD only opens one socket for both Discovery and Session packets */
291 #if defined(__FreeBSD__)
292     /* Confirmed for FreeBSD 4.8-R [SeaD] */
293     if (!hwaddr) {
294 #else
295     if (fd >= 0) {
296 #endif
297 	return fd;
298     }
299 
300     /* Find a free BPF device */
301     for (i = 0; i < 256; i++) {
302 	sprintf(bpfName, "/dev/bpf%d", i);
303 	if (((fd = open(bpfName, O_RDWR, 0)) >= 0) ||
304 	    (errno != EBUSY)) {
305 	    break;
306 	}
307     }
308     if (fd < 0) {
309 	switch (errno) {
310 	case EACCES:		/* permission denied */
311 	    {
312 		char buffer[256];
313 		sprintf(buffer, "Cannot open %.32s -- pppoe must be run as root.", bpfName);
314 		rp_fatal(buffer);
315 	    }
316 	    break;
317 	case EBUSY:
318 	case ENOENT:		/* no such file */
319 	    if (i == 0) {
320 		rp_fatal("No /dev/bpf* devices (check your kernel configuration for BPF support)");
321 	    } else {
322 		rp_fatal("All /dev/bpf* devices are in use");
323 	    }
324 	    break;
325 	}
326 	fatalSys(bpfName);
327     }
328 
329     if ((sock = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0) {
330 	fatalSys("socket");
331     }
332 
333     /* Check that the interface is up */
334     strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
335     if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
336 	fatalSys("ioctl(SIOCGIFFLAGS)");
337     }
338     if ((ifr.ifr_flags & IFF_UP) == 0) {
339 	char buffer[256];
340 	sprintf(buffer, "Interface %.16s is not up", ifname);
341 	rp_fatal(buffer);
342     }
343 
344     /* Fill in hardware address and initialize the packet filter rules */
345     if (hwaddr == NULL) {
346 	rp_fatal("openInterface: no hwaddr arg.");
347     }
348     getHWaddr(sock, ifname, hwaddr);
349     initFilter(fd, type, hwaddr);
350 
351     /* Sanity check on MTU -- apparently does not work on OpenBSD */
352 #if !defined(__OpenBSD__)
353     strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
354     if (ioctl(sock, SIOCGIFMTU, &ifr) < 0) {
355 	fatalSys("ioctl(SIOCGIFMTU)");
356     }
357     if (ifr.ifr_mtu < ETH_DATA_LEN) {
358 	char buffer[256];
359 	sprintf(buffer, "Interface %.16s has MTU of %d -- should be %d.  You may have serious connection problems.",
360 		ifname, ifr.ifr_mtu, ETH_DATA_LEN);
361 	printErr(buffer);
362     }
363 #endif
364 
365     /* done with the socket */
366     if (close(sock) < 0) {
367 	fatalSys("close");
368     }
369 
370     /* Check the BPF version number */
371     if (ioctl(fd, BIOCVERSION, &bpf_ver) < 0) {
372 	fatalSys("ioctl(BIOCVERSION)");
373     }
374     if ((bpf_ver.bv_major != BPF_MAJOR_VERSION) ||
375 	(bpf_ver.bv_minor < BPF_MINOR_VERSION)) {
376 	char buffer[256];
377 	sprintf(buffer, "Unsupported BPF version: %d.%d (kernel: %d.%d)",
378 			BPF_MAJOR_VERSION, BPF_MINOR_VERSION,
379 			bpf_ver.bv_major, bpf_ver.bv_minor);
380 	rp_fatal(buffer);
381     }
382 
383     /* allocate a receive packet buffer */
384     if (ioctl(fd, BIOCGBLEN, &bpfLength) < 0) {
385 	fatalSys("ioctl(BIOCGBLEN)");
386     }
387     if (!(bpfBuffer = (unsigned char *) malloc(bpfLength))) {
388 	rp_fatal("malloc");
389     }
390 
391     /* reads should return as soon as there is a packet available */
392     optval = 1;
393     if (ioctl(fd, BIOCIMMEDIATE, &optval) < 0) {
394 	fatalSys("ioctl(BIOCIMMEDIATE)");
395     }
396 
397     /* Bind the interface to the filter */
398     strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
399     if (ioctl(fd, BIOCSETIF, &ifr) < 0) {
400 	char buffer[256];
401 	sprintf(buffer, "ioctl(BIOCSETIF) can't select interface %.16s",
402 		ifname);
403 	rp_fatal(buffer);
404     }
405 
406     if (mtu) *mtu = ifr.ifr_mtu;
407 
408     syslog(LOG_INFO, "Interface=%.16s HWaddr=%02X:%02X:%02X:%02X:%02X:%02X Device=%.32s Buffer size=%d",
409 	   ifname,
410 	   hwaddr[0], hwaddr[1], hwaddr[2],
411 	   hwaddr[3], hwaddr[4], hwaddr[5],
412 	   bpfName, bpfLength);
413     return fd;
414 }
415 
416 #endif /* USE_BPF */
417 
418 #ifdef USE_LINUX_PACKET
419 /**********************************************************************
420 *%FUNCTION: openInterface
421 *%ARGUMENTS:
422 * ifname -- name of interface
423 * type -- Ethernet frame type
424 * hwaddr -- if non-NULL, set to the hardware address
425 * mtu    -- if non-NULL, set to the MTU
426 *%RETURNS:
427 * A raw socket for talking to the Ethernet card.  Exits on error.
428 *%DESCRIPTION:
429 * Opens a raw Ethernet socket
430 ***********************************************************************/
431 int
432 openInterface(char const *ifname, UINT16_t type, unsigned char *hwaddr, UINT16_t *mtu)
433 {
434     int optval=1;
435     int fd;
436     struct ifreq ifr;
437     int domain, stype;
438 
439 #ifdef HAVE_STRUCT_SOCKADDR_LL
440     struct sockaddr_ll sa;
441 #else
442     struct sockaddr sa;
443 #endif
444 
445     memset(&sa, 0, sizeof(sa));
446 
447 #ifdef HAVE_STRUCT_SOCKADDR_LL
448     domain = PF_PACKET;
449     stype = SOCK_RAW;
450 #else
451     domain = PF_INET;
452     stype = SOCK_PACKET;
453 #endif
454 
455     if ((fd = socket(domain, stype, htons(type))) < 0) {
456 	/* Give a more helpful message for the common error case */
457 	if (errno == EPERM) {
458 	    rp_fatal("Cannot create raw socket -- pppoe must be run as root.");
459 	}
460 	fatalSys("socket");
461     }
462 
463     if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) < 0) {
464 	fatalSys("setsockopt");
465     }
466 
467     /* Fill in hardware address */
468     if (hwaddr) {
469 	strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
470 	if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
471 	    fatalSys("ioctl(SIOCGIFHWADDR)");
472 	}
473 	memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
474 #ifdef ARPHRD_ETHER
475 	if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
476 	    char buffer[256];
477 	    sprintf(buffer, "Interface %.16s is not Ethernet", ifname);
478 	    rp_fatal(buffer);
479 	}
480 #endif
481 	if (NOT_UNICAST(hwaddr)) {
482 	    char buffer[256];
483 	    sprintf(buffer,
484 		    "Interface %.16s has broadcast/multicast MAC address??",
485 		    ifname);
486 	    rp_fatal(buffer);
487 	}
488     }
489 
490     /* Sanity check on MTU */
491     strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
492     if (ioctl(fd, SIOCGIFMTU, &ifr) < 0) {
493 	fatalSys("ioctl(SIOCGIFMTU)");
494     }
495     if (ifr.ifr_mtu < ETH_DATA_LEN) {
496 	char buffer[256];
497 	sprintf(buffer, "Interface %.16s has MTU of %d -- should be %d.  You may have serious connection problems.",
498 		ifname, ifr.ifr_mtu, ETH_DATA_LEN);
499 	printErr(buffer);
500     }
501     if (mtu) *mtu = ifr.ifr_mtu;
502 
503 #ifdef HAVE_STRUCT_SOCKADDR_LL
504     /* Get interface index */
505     sa.sll_family = AF_PACKET;
506     sa.sll_protocol = htons(type);
507 
508     strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
509     if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
510 	fatalSys("ioctl(SIOCFIGINDEX): Could not get interface index");
511     }
512     sa.sll_ifindex = ifr.ifr_ifindex;
513 
514 #else
515     strcpy(sa.sa_data, ifname);
516 #endif
517 
518     /* We're only interested in packets on specified interface */
519     if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
520 	fatalSys("bind");
521     }
522 
523     return fd;
524 }
525 
526 #endif /* USE_LINUX */
527 
528 /***********************************************************************
529 *%FUNCTION: sendPacket
530 *%ARGUMENTS:
531 * sock -- socket to send to
532 * pkt -- the packet to transmit
533 * size -- size of packet (in bytes)
534 *%RETURNS:
535 * 0 on success; -1 on failure
536 *%DESCRIPTION:
537 * Transmits a packet
538 ***********************************************************************/
539 int
540 sendPacket(PPPoEConnection *conn, int sock, PPPoEPacket *pkt, int size)
541 {
542 #if defined(USE_BPF)
543     if (write(sock, pkt, size) < 0) {
544 	sysErr("write (sendPacket)");
545 	return -1;
546     }
547 #elif defined(HAVE_STRUCT_SOCKADDR_LL)
548     if (send(sock, pkt, size, 0) < 0 && (errno != ENOBUFS)) {
549 	sysErr("send (sendPacket)");
550 	return -1;
551     }
552 #else
553 #ifdef USE_DLPI
554 
555 #define ABS(x)          ((x) < 0 ? -(x) : (x))
556 
557 	u_char  addr[MAXDLADDR];
558 	u_char  phys[MAXDLADDR];
559 	u_char  sap[MAXDLADDR];
560 	u_char    xmitbuf[MAXDLBUF];
561 	int	data_size;
562 
563 	short	tmp_sap;
564 
565 	tmp_sap = htons(pkt->ethHdr.h_proto);
566 	data_size = size - sizeof(struct ethhdr);
567 
568 	memcpy((char *)phys, (char *)pkt->ethHdr.h_dest, ETHERADDRL);
569 	memcpy((char *)sap,  (char *)&tmp_sap, sizeof(ushort_t));
570 	memcpy((char *)xmitbuf, (char *)pkt + sizeof(struct ethhdr), data_size);
571 
572 	if (dl_saplen > 0) {  /* order is sap+phys */
573 		(void) memcpy((char*)addr, (char*)&sap, dl_abssaplen);
574 		(void) memcpy((char*)addr+dl_abssaplen, (char*)phys, ETHERADDRL);
575 	} else {        /* order is phys+sap */
576 		(void) memcpy((char*)addr, (char*)phys, ETHERADDRL);
577 		(void) memcpy((char*)addr+ETHERADDRL, (char*)&sap, dl_abssaplen);
578 	}
579 
580 #ifdef DL_DEBUG
581 	printf("%02x:%02x:%02x:%02x:%02x:%02x %02x:%02x\n",
582 		addr[0],addr[1],addr[2],addr[3],addr[4],addr[5],
583 		addr[6],addr[7]);
584 #endif
585 
586 	dlunitdatareq(sock, addr, dl_addrlen, 0, 0, xmitbuf, data_size);
587 
588 
589 
590 #else
591     struct sockaddr sa;
592 
593     if (!conn) {
594 	rp_fatal("relay and server not supported on Linux 2.0 kernels");
595     }
596     strcpy(sa.sa_data, conn->ifName);
597     if (sendto(sock, pkt, size, 0, &sa, sizeof(sa)) < 0) {
598 	sysErr("sendto (sendPacket)");
599 	return -1;
600     }
601 #endif
602 #endif
603     return 0;
604 }
605 
606 #ifdef USE_BPF
607 /***********************************************************************
608 *%FUNCTION: clearPacketHeader
609 *%ARGUMENTS:
610 * pkt -- packet that needs its head clearing
611 *%RETURNS:
612 * nothing
613 *%DESCRIPTION:
614 * Clears a PPPoE packet header after a truncated packet has been
615 * received.  Insures that the packet will fail any integrity tests
616 * and will be discarded by upper level routines.  Also resets the
617 * bpfSize and bpfOffset variables to force a new read on the next
618 * call to receivePacket().
619 ***********************************************************************/
620 void
621 clearPacketHeader(PPPoEPacket *pkt)
622 {
623     bpfSize = bpfOffset = 0;
624     memset(pkt, 0, HDR_SIZE);
625 }
626 #endif
627 
628 /***********************************************************************
629 *%FUNCTION: receivePacket
630 *%ARGUMENTS:
631 * sock -- socket to read from
632 * pkt -- place to store the received packet
633 * size -- set to size of packet in bytes
634 *%RETURNS:
635 * >= 0 if all OK; < 0 if error
636 *%DESCRIPTION:
637 * Receives a packet
638 ***********************************************************************/
639 int
640 receivePacket(int sock, PPPoEPacket *pkt, int *size)
641 {
642 #ifdef USE_BPF
643     struct bpf_hdr hdr;
644     int seglen, copylen;
645 
646     if (bpfSize <= 0) {
647 	bpfOffset = 0;
648 	if ((bpfSize = read(sock, bpfBuffer, bpfLength)) < 0) {
649 	    sysErr("read (receivePacket)");
650 	    return -1;
651 	}
652     }
653     if (bpfSize < sizeof(hdr)) {
654 	syslog(LOG_ERR, "Truncated bpf packet header: len=%d", bpfSize);
655 	clearPacketHeader(pkt);		/* resets bpfSize and bpfOffset */
656 	return 0;
657     }
658     memcpy(&hdr, bpfBuffer + bpfOffset, sizeof(hdr));
659     if (hdr.bh_caplen != hdr.bh_datalen) {
660 	syslog(LOG_ERR, "Truncated bpf packet: caplen=%d, datalen=%d",
661 	       hdr.bh_caplen, hdr.bh_datalen);
662 	clearPacketHeader(pkt);		/* resets bpfSize and bpfOffset */
663 	return 0;
664     }
665     seglen = hdr.bh_hdrlen + hdr.bh_caplen;
666     if (seglen > bpfSize) {
667 	syslog(LOG_ERR, "Truncated bpf packet: seglen=%d, bpfSize=%d",
668 	       seglen, bpfSize);
669 	clearPacketHeader(pkt);		/* resets bpfSize and bpfOffset */
670 	return 0;
671     }
672     seglen = BPF_WORDALIGN(seglen);
673     *size = copylen = ((hdr.bh_caplen < sizeof(PPPoEPacket)) ?
674 			hdr.bh_caplen : sizeof(PPPoEPacket));
675     memcpy(pkt, bpfBuffer + bpfOffset + hdr.bh_hdrlen, copylen);
676     if (seglen >= bpfSize) {
677 	bpfSize = bpfOffset = 0;
678     } else {
679 	bpfSize -= seglen;
680 	bpfOffset += seglen;
681     }
682 #else
683 #ifdef USE_DLPI
684 	struct strbuf data;
685 	int flags = 0;
686 	int retval;
687 
688 	data.buf = (char *) pkt;
689 	data.maxlen = MAXDLBUF;
690 	data.len = 0;
691 
692 	if ((retval = getmsg(sock, NULL, &data, &flags)) < 0) {
693 	    sysErr("read (receivePacket)");
694 	    return -1;
695 	}
696 
697 	*size = data.len;
698 
699 #else
700     if ((*size = recv(sock, pkt, sizeof(PPPoEPacket), 0)) < 0) {
701 	sysErr("recv (receivePacket)");
702 	return -1;
703     }
704 #endif
705 #endif
706     return 0;
707 }
708 
709 #ifdef USE_DLPI
710 /**********************************************************************
711 *%FUNCTION: openInterface
712 *%ARGUMENTS:
713 * ifname -- name of interface
714 * type -- Ethernet frame type
715 * hwaddr -- if non-NULL, set to the hardware address
716 *%RETURNS:
717 * A raw socket for talking to the Ethernet card.  Exits on error.
718 *%DESCRIPTION:
719 * Opens a raw Ethernet socket
720 ***********************************************************************/
721 int
722 openInterface(char const *ifname, UINT16_t type, unsigned char *hwaddr)
723 {
724     int fd;
725     long buf[MAXDLBUF];
726 
727     union   DL_primitives   *dlp;
728 
729     char base_dev[PATH_MAX];
730     int ppa;
731 
732     if(strlen(ifname) > PATH_MAX) {
733 	rp_fatal("socket: Interface name too long");
734     }
735 
736     if (strlen(ifname) < 2) {
737 	rp_fatal("socket: Interface name too short");
738     }
739 
740     ppa = atoi(&ifname[strlen(ifname)-1]);
741     strlcpy(base_dev, ifname, PATH_MAX);
742 
743 /* rearranged order of DLPI code - delphys 20010803 */
744     dlp = (union DL_primitives*) buf;
745 
746     if ( (fd = open(base_dev, O_RDWR)) < 0) {
747 	/* Give a more helpful message for the common error case */
748 	if (errno == EPERM) {
749 	    rp_fatal("Cannot create raw socket -- pppoe must be run as root.");
750 	}
751 	/* Common error is to omit /dev/ */
752 	if (errno == ENOENT) {
753 	    char ifname[512];
754 	    snprintf(ifname, sizeof(ifname), "/dev/%s", base_dev);
755 	    if ((fd = open(ifname, O_RDWR)) < 0) {
756 		if (errno == EPERM) {
757 		    rp_fatal("Cannot create raw socket -- pppoe must be run as root.");
758 		}
759 	    }
760 	}
761     }
762     if (fd < 0) {
763 	fatalSys("socket");
764     }
765 
766 /* rearranged order of DLPI code - delphys 20010803 */
767     dlattachreq(fd, ppa);
768     dlokack(fd, (char *)buf);
769 
770     dlbindreq(fd, type, 0, DL_CLDLS, 0, 0);
771     dlbindack(fd, (char *)buf);
772 
773     dlinforeq(fd);
774     dlinfoack(fd, (char *)buf);
775 
776     dl_abssaplen = ABS(dlp->info_ack.dl_sap_length);
777     dl_saplen = dlp->info_ack.dl_sap_length;
778     if (ETHERADDRL != (dlp->info_ack.dl_addr_length - dl_abssaplen))
779 	fatalSys("invalid destination physical address length");
780     dl_addrlen = dl_abssaplen + ETHERADDRL;
781 
782 /* ethernet address retrieved as part of DL_INFO_ACK - delphys 20010803 */
783     memcpy(hwaddr, (u_char*)((char*)(dlp) + (int)(dlp->info_ack.dl_addr_offset)), ETHERADDRL);
784 
785     if ( strioctl(fd, DLIOCRAW, -1, 0, NULL) < 0 ) {
786 	fatalSys("DLIOCRAW");
787     }
788 
789     if (ioctl(fd, I_FLUSH, FLUSHR) < 0) fatalSys("I_FLUSH");
790 
791     return fd;
792 }
793 
794 /* cloned from dlcommon.c */
795 
796 static void
797 dlpromisconreq(int fd, u_long level)
798 {
799 	dl_promiscon_req_t      promiscon_req;
800 	struct  strbuf  ctl;
801 	int     flags;
802 
803 	promiscon_req.dl_primitive = DL_PROMISCON_REQ;
804 	promiscon_req.dl_level = level;
805 
806 	ctl.maxlen = 0;
807 	ctl.len = sizeof (promiscon_req);
808 	ctl.buf = (char *) &promiscon_req;
809 
810 	flags = 0;
811 
812 	if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
813 		fatalSys("dlpromiscon:  putmsg");
814 
815 }
816 
817 void dlinforeq(int fd)
818 {
819 	dl_info_req_t   info_req;
820 	struct  strbuf  ctl;
821 	int     flags;
822 
823 	info_req.dl_primitive = DL_INFO_REQ;
824 
825 	ctl.maxlen = 0;
826 	ctl.len = sizeof (info_req);
827 	ctl.buf = (char *) &info_req;
828 
829 	flags = RS_HIPRI;
830 
831 	if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
832 		fatalSys("dlinforeq:  putmsg");
833 }
834 
835 void dlunitdatareq(int fd, u_char *addrp, int addrlen, u_long minpri, u_long maxpri, u_char *datap, int datalen)
836 {
837 	long    buf[MAXDLBUF];
838 	union   DL_primitives   *dlp;
839 	struct  strbuf  data, ctl;
840 
841 	dlp = (union DL_primitives*) buf;
842 
843 	dlp->unitdata_req.dl_primitive = DL_UNITDATA_REQ;
844 	dlp->unitdata_req.dl_dest_addr_length = addrlen;
845 	dlp->unitdata_req.dl_dest_addr_offset = sizeof (dl_unitdata_req_t);
846 	dlp->unitdata_req.dl_priority.dl_min = minpri;
847 	dlp->unitdata_req.dl_priority.dl_max = maxpri;
848 
849 	(void) memcpy(OFFADDR(dlp, sizeof (dl_unitdata_req_t)), addrp, addrlen);
850 
851 	ctl.maxlen = 0;
852 	ctl.len = sizeof (dl_unitdata_req_t) + addrlen;
853 	ctl.buf = (char *) buf;
854 
855 	data.maxlen = 0;
856 	data.len = datalen;
857 	data.buf = (char *) datap;
858 
859 	if (putmsg(fd, &ctl, &data, 0) < 0)
860 		fatalSys("dlunitdatareq:  putmsg");
861 }
862 
863 void dlinfoack(int fd, char *bufp)
864 {
865 	union   DL_primitives   *dlp;
866 	struct  strbuf  ctl;
867 	int     flags;
868 
869 	ctl.maxlen = MAXDLBUF;
870 	ctl.len = 0;
871 	ctl.buf = bufp;
872 
873 	strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlinfoack");
874 
875 	dlp = (union DL_primitives *) ctl.buf;
876 
877 	expecting(DL_INFO_ACK, dlp);
878 
879 	if (ctl.len < sizeof (dl_info_ack_t)) {
880 		char buffer[256];
881 		sprintf(buffer, "dlinfoack:  response ctl.len too short:  %d", ctl.len);
882 		rp_fatal(buffer);
883 	}
884 
885 	if (flags != RS_HIPRI)
886 		rp_fatal("dlinfoack:  DL_INFO_ACK was not M_PCPROTO");
887 
888 	if (ctl.len < sizeof (dl_info_ack_t)) {
889 		char buffer[256];
890 		sprintf(buffer, "dlinfoack:  short response ctl.len:  %d", ctl.len);
891 		rp_fatal(buffer);
892 	}
893 }
894 
895 void dlbindreq(int fd, u_long sap, u_long max_conind, u_long service_mode, u_long conn_mgmt, u_long xidtest)
896 {
897 	dl_bind_req_t   bind_req;
898 	struct  strbuf  ctl;
899 	int     flags;
900 
901 	bind_req.dl_primitive = DL_BIND_REQ;
902 	bind_req.dl_sap = sap;
903 	bind_req.dl_max_conind = max_conind;
904 	bind_req.dl_service_mode = service_mode;
905 	bind_req.dl_conn_mgmt = conn_mgmt;
906 	bind_req.dl_xidtest_flg = xidtest;
907 
908 	ctl.maxlen = 0;
909 	ctl.len = sizeof (bind_req);
910 	ctl.buf = (char *) &bind_req;
911 
912 	flags = 0;
913 
914 	if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
915 		fatalSys("dlbindreq:  putmsg");
916 }
917 
918 void dlattachreq(int fd, u_long ppa)
919 {
920 	dl_attach_req_t attach_req;
921 	struct  strbuf  ctl;
922 	int     flags;
923 
924 	attach_req.dl_primitive = DL_ATTACH_REQ;
925 	attach_req.dl_ppa = ppa;
926 
927 	ctl.maxlen = 0;
928 	ctl.len = sizeof (attach_req);
929 	ctl.buf = (char *) &attach_req;
930 
931 	flags = 0;
932 
933 	if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
934 		fatalSys("dlattachreq:  putmsg");
935 }
936 
937 void dlokack(int fd, char *bufp)
938 {
939 	union   DL_primitives   *dlp;
940 	struct  strbuf  ctl;
941 	int     flags;
942 
943 	ctl.maxlen = MAXDLBUF;
944 	ctl.len = 0;
945 	ctl.buf = bufp;
946 
947 	strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlokack");
948 
949 	dlp = (union DL_primitives *) ctl.buf;
950 
951 	expecting(DL_OK_ACK, dlp);
952 
953 	if (ctl.len < sizeof (dl_ok_ack_t)) {
954 		char buffer[256];
955 		sprintf(buffer, "dlokack:  response ctl.len too short:  %d", ctl.len);
956 		rp_fatal(buffer);
957 	}
958 
959 	if (flags != RS_HIPRI)
960 		rp_fatal("dlokack:  DL_OK_ACK was not M_PCPROTO");
961 
962 	if (ctl.len < sizeof (dl_ok_ack_t)) {
963 		char buffer[256];
964 		sprintf(buffer, "dlokack:  short response ctl.len:  %d", ctl.len);
965 		rp_fatal(buffer);
966 	}
967 }
968 
969 void dlbindack(int fd, char *bufp)
970 {
971 	union   DL_primitives   *dlp;
972 	struct  strbuf  ctl;
973 	int     flags;
974 
975 	ctl.maxlen = MAXDLBUF;
976 	ctl.len = 0;
977 	ctl.buf = bufp;
978 
979 	strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlbindack");
980 
981 	dlp = (union DL_primitives *) ctl.buf;
982 
983 	expecting(DL_BIND_ACK, dlp);
984 
985 	if (flags != RS_HIPRI)
986 		rp_fatal("dlbindack:  DL_OK_ACK was not M_PCPROTO");
987 
988 	if (ctl.len < sizeof (dl_bind_ack_t)) {
989 		char buffer[256];
990 		sprintf(buffer, "dlbindack:  short response ctl.len:  %d", ctl.len);
991 		rp_fatal(buffer);
992 	}
993 }
994 
995 int strioctl(int fd, int cmd, int timout, int len, char *dp)
996 {
997 	struct  strioctl        sioc;
998 	int     rc;
999 
1000 	sioc.ic_cmd = cmd;
1001 	sioc.ic_timout = timout;
1002 	sioc.ic_len = len;
1003 	sioc.ic_dp = dp;
1004 	rc = ioctl(fd, I_STR, &sioc);
1005 
1006 	if (rc < 0)
1007 		return (rc);
1008 	else
1009 		return (sioc.ic_len);
1010 }
1011 
1012 void strgetmsg(int fd, struct strbuf *ctlp, struct strbuf *datap, int *flagsp, char *caller)
1013 {
1014 	int     rc;
1015 	static  char    errmsg[80];
1016 
1017 	/*
1018 	 * Start timer.
1019 	 */
1020 	(void) signal(SIGALRM, sigalrm);
1021 	if (alarm(MAXWAIT) < 0) {
1022 		(void) sprintf(errmsg, "%s:  alarm", caller);
1023 		fatalSys(errmsg);
1024 	}
1025 
1026 	/*
1027 	 * Set flags argument and issue getmsg().
1028 	 */
1029 	*flagsp = 0;
1030 	if ((rc = getmsg(fd, ctlp, datap, flagsp)) < 0) {
1031 		(void) sprintf(errmsg, "%s:  getmsg", caller);
1032 		fatalSys(errmsg);
1033 	}
1034 
1035 	/*
1036 	 * Stop timer.
1037 	 */
1038 	if (alarm(0) < 0) {
1039 		(void) sprintf(errmsg, "%s:  alarm", caller);
1040 		fatalSys(errmsg);
1041 	}
1042 
1043 	/*
1044 	 * Check for MOREDATA and/or MORECTL.
1045 	 */
1046 	if ((rc & (MORECTL | MOREDATA)) == (MORECTL | MOREDATA)) {
1047 		char buffer[256];
1048 		sprintf(buffer, "%s:  MORECTL|MOREDATA", caller);
1049 		rp_fatal(buffer);
1050 	}
1051 
1052 	if (rc & MORECTL) {
1053 		char buffer[256];
1054 		sprintf(buffer, "%s:  MORECTL", caller);
1055 		rp_fatal(buffer);
1056 	}
1057 
1058 	if (rc & MOREDATA) {
1059 		char buffer[256];
1060 		sprintf(buffer, "%s:  MOREDATA", caller);
1061 		rp_fatal(buffer);
1062 	}
1063 
1064 	/*
1065 	 * Check for at least sizeof (long) control data portion.
1066 	 */
1067 	if (ctlp->len < sizeof (long)) {
1068 		char buffer[256];
1069 		sprintf(buffer, "getmsg:  control portion length < sizeof (long):  %d", ctlp->len);
1070 		rp_fatal(buffer);
1071 	}
1072 }
1073 
1074 void sigalrm(int sig)
1075 {
1076 	(void) rp_fatal("sigalrm:  TIMEOUT");
1077 }
1078 
1079 void expecting(int prim, union DL_primitives *dlp)
1080 {
1081 	if (dlp->dl_primitive != (u_long)prim) {
1082 		char buffer[256];
1083 		sprintf(buffer, "expected %s got %s", dlprim(prim), dlprim(dlp->dl_primitive));
1084 		rp_fatal(buffer);
1085 		exit(1);
1086 	}
1087 }
1088 
1089 static char *
1090 dlprim(u_long prim)
1091 {
1092 	static  char    primbuf[80];
1093 
1094 	switch ((int)prim) {
1095 		CASERET(DL_INFO_REQ);
1096 		CASERET(DL_INFO_ACK);
1097 		CASERET(DL_ATTACH_REQ);
1098 		CASERET(DL_DETACH_REQ);
1099 		CASERET(DL_BIND_REQ);
1100 		CASERET(DL_BIND_ACK);
1101 		CASERET(DL_UNBIND_REQ);
1102 		CASERET(DL_OK_ACK);
1103 		CASERET(DL_ERROR_ACK);
1104 		CASERET(DL_SUBS_BIND_REQ);
1105 		CASERET(DL_SUBS_BIND_ACK);
1106 		CASERET(DL_UNITDATA_REQ);
1107 		CASERET(DL_UNITDATA_IND);
1108 		CASERET(DL_UDERROR_IND);
1109 		CASERET(DL_UDQOS_REQ);
1110 		CASERET(DL_CONNECT_REQ);
1111 		CASERET(DL_CONNECT_IND);
1112 		CASERET(DL_CONNECT_RES);
1113 		CASERET(DL_CONNECT_CON);
1114 		CASERET(DL_TOKEN_REQ);
1115 		CASERET(DL_TOKEN_ACK);
1116 		CASERET(DL_DISCONNECT_REQ);
1117 		CASERET(DL_DISCONNECT_IND);
1118 		CASERET(DL_RESET_REQ);
1119 		CASERET(DL_RESET_IND);
1120 		CASERET(DL_RESET_RES);
1121 		CASERET(DL_RESET_CON);
1122 		default:
1123 			(void) sprintf(primbuf, "unknown primitive 0x%lx", prim);
1124 			return (primbuf);
1125 	}
1126 }
1127 
1128 #endif /* USE_DLPI */
1129