18ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/***********************************************************************
28ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*
38ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* if.c
48ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*
58ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Implementation of user-space PPPoE redirector for Linux.
68ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*
78ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Functions for opening a raw socket and reading/writing raw Ethernet frames.
88ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*
98ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Copyright (C) 2000 by Roaring Penguin Software Inc.
108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*
118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* This program may be distributed according to the terms of the GNU
128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* General Public License, version 2 or (at your option) any later version.
138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*
148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic char const RCSID[] =
178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project"$Id: if.c,v 1.1 2001/12/14 02:55:20 mostrows Exp $";
188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include "pppoe.h"
208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef HAVE_UNISTD_H
228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <unistd.h>
238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef HAVE_NETPACKET_PACKET_H
268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <netpacket/packet.h>
278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#elif defined(HAVE_LINUX_IF_PACKET_H)
288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <linux/if_packet.h>
298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef HAVE_NET_ETHERNET_H
328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <net/ethernet.h>
338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef HAVE_ASM_TYPES_H
368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <asm/types.h>
378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef HAVE_SYS_IOCTL_H
408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <sys/ioctl.h>
418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef HAVE_SYSLOG_H
448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <syslog.h>
458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <errno.h>
488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <stdlib.h>
498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <string.h>
508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef HAVE_NET_IF_ARP_H
528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <net/if_arp.h>
538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef USE_DLPI
568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <limits.h>
588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <fcntl.h>
598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <stdlib.h>
608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <sys/types.h>
618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <sys/time.h>
628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <sys/stream.h>
638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <sys/stropts.h>
648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <sys/dlpi.h>
658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <sys/bufmod.h>
668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <stdio.h>
678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <signal.h>
688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <stropts.h>
698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/* function declarations */
718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid dlpromisconreq( int fd, u_long  level);
738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid dlinforeq(int fd);
748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid dlunitdatareq(int fd, u_char *addrp, int addrlen, u_long minpri, u_long maxpri, u_char *datap, int datalen);
758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid dlinfoack(int fd, char *bufp);
768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid dlbindreq(int fd, u_long sap, u_long max_conind, u_long service_mode, u_long conn_mgmt, u_long xidtest);
778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid dlattachreq(int fd, u_long ppa);
788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid dlokack(int fd, char *bufp);
798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid dlbindack(int fd, char *bufp);
808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectint strioctl(int fd, int cmd, int timout, int len, char *dp);
818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid strgetmsg(int fd, struct strbuf *ctlp, struct strbuf *datap, int *flagsp, char *caller);
828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid sigalrm(int sig);
838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid expecting(int prim, union DL_primitives *dlp);
848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectchar *dlprim(u_long prim);
858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/* #define DL_DEBUG */
878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic	int     dl_abssaplen;
898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic	int     dl_saplen;
908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic	int 	dl_addrlen;
918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef USE_BPF
958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <net/bpf.h>
968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <fcntl.h>
978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectunsigned char *bpfBuffer;	/* Packet filter buffer */
998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectint bpfLength = 0;		/* Packet filter buffer length */
1008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectint bpfSize = 0;		/* Number of unread bytes in buffer */
1018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectint bpfOffset = 0;		/* Current offset in bpfBuffer */
1028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
1038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/* Initialize frame types to RFC 2516 values.  Some broken peers apparently
1058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project   use different frame types... sigh... */
1068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectUINT16_t Eth_PPPOE_Discovery = ETH_PPPOE_DISCOVERY;
1088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectUINT16_t Eth_PPPOE_Session   = ETH_PPPOE_SESSION;
1098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/**********************************************************************
1118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%FUNCTION: etherType
1128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%ARGUMENTS:
1138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* packet -- a received PPPoE packet
1148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%RETURNS:
1158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* ethernet packet type (see /usr/include/net/ethertypes.h)
1168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%DESCRIPTION:
1178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Checks the ethernet packet header to determine its type.
1188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* We should only be receveing DISCOVERY and SESSION types if the BPF
1198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* is set up correctly.  Logs an error if an unexpected type is received.
1208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Note that the ethernet type names come from "pppoe.h" and the packet
1218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* packet structure names use the LINUX dialect to maintain consistency
1228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* with the rest of this file.  See the BSD section of "pppoe.h" for
1238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* translations of the data structure names.
1248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
1258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectUINT16_t
1268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectetherType(PPPoEPacket *packet)
1278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
1288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    UINT16_t type = (UINT16_t) ntohs(packet->ethHdr.h_proto);
1298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (type != Eth_PPPOE_Discovery && type != Eth_PPPOE_Session) {
1308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	syslog(LOG_ERR, "Invalid ether type 0x%x", type);
1318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
1328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    return type;
1338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
1348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef USE_BPF
1368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/**********************************************************************
1378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%FUNCTION: getHWaddr
1388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%ARGUMENTS:
1398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* ifname -- name of interface
1408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* hwaddr -- buffer for ehthernet address
1418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%RETURNS:
1428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Nothing
1438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%DESCRIPTION:
1448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Locates the Ethernet hardware address for an interface.
1458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
1468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid
1478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectgetHWaddr(int sock, char const *ifname, unsigned char *hwaddr)
1488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
1498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    char inbuf[8192];
1508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    const struct sockaddr_dl *sdl;
1518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    struct ifconf ifc;
1528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    struct ifreq ifreq, *ifr;
1538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    int i;
1548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    int found = 0;
1558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    ifc.ifc_len = sizeof(inbuf);
1578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    ifc.ifc_buf = inbuf;
1588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
1598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fatalSys("SIOCGIFCONF");
1608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
1618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    ifr = ifc.ifc_req;
1628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    ifreq.ifr_name[0] = '\0';
1638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    for (i = 0; i < ifc.ifc_len; ) {
1648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	ifr = (struct ifreq *)((caddr_t)ifc.ifc_req + i);
1658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	i += sizeof(ifr->ifr_name) +
1668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    (ifr->ifr_addr.sa_len > sizeof(struct sockaddr)
1678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    ? ifr->ifr_addr.sa_len
1688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    : sizeof(struct sockaddr));
1698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (ifr->ifr_addr.sa_family == AF_LINK) {
1708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    sdl = (const struct sockaddr_dl *) &ifr->ifr_addr;
1718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    if ((sdl->sdl_type == IFT_ETHER) &&
1728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	        (sdl->sdl_alen == ETH_ALEN) &&
1738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		!strncmp(ifname, ifr->ifr_name, sizeof(ifr->ifr_name))) {
1748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		if (found) {
1758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    char buffer[256];
1768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    sprintf(buffer, "interface %.16s has more than one ethernet address", ifname);
1778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    rp_fatal(buffer);
1788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		} else {
1798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    found = 1;
1808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	            memcpy(hwaddr, LLADDR(sdl), ETH_ALEN);
1818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		}
1828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    }
1838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
1848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
1858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (!found) {
1868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	char buffer[256];
1878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        sprintf(buffer, "interface %.16s has no ethernet address", ifname);
1888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	rp_fatal(buffer);
1898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
1908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
1918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/**********************************************************************
1938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%FUNCTION: initFilter
1948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%ARGUMENTS:
1958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* fd -- file descriptor of BSD device
1968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* type -- Ethernet frame type (0 for watch mode)
1978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* hwaddr -- buffer with ehthernet address
1988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%RETURNS:
1998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Nothing
2008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%DESCRIPTION:
2018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Initializes the packet filter rules.
2028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
2038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid
2048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectinitFilter(int fd, UINT16_t type, unsigned char *hwaddr)
2058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
2068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Packet Filter Instructions:
2078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project     * Note that the ethernet type names come from "pppoe.h" and are
2088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project     * used here to maintain consistency with the rest of this file. */
2098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    static struct bpf_insn bpfRun[] = {         /* run PPPoE */
2108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12),     /* ethernet type */
2118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETH_PPPOE_SESSION, 5, 0),
2128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETH_PPPOE_DISCOVERY, 0, 9),
2138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 0),      /* first word of dest. addr */
2148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#define PPPOE_BCAST_CMPW 4                     /* offset of word compare */
2158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 2),
2168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 4),      /* next 1/2 word of dest. */
2178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#define PPPOE_BCAST_CMPH 6                     /* offset of 1/2 word compare */
2188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 4, 0),
2198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 0),      /* first word of dest. addr */
2208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#define PPPOE_FILTER_CMPW 8                     /* offset of word compare */
2218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 3),
2228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 4),      /* next 1/2 word of dest. */
2238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#define PPPOE_FILTER_CMPH 10                    /* offset of 1/rd compare */
2248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 1),
2258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        BPF_STMT(BPF_RET+BPF_K, (u_int) -1),    /* keep packet */
2268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        BPF_STMT(BPF_RET+BPF_K, 0),             /* drop packet */
2278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    };
2288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Fix the potentially varying parts */
2308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    bpfRun[1].code = (u_short) BPF_JMP+BPF_JEQ+BPF_K;
2318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    bpfRun[1].jt   = 5;
2328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    bpfRun[1].jf   = 0;
2338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    bpfRun[1].k    = Eth_PPPOE_Session;
2348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    bpfRun[2].code = (u_short) BPF_JMP+BPF_JEQ+BPF_K;
2368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    bpfRun[2].jt   = 0;
2378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    bpfRun[2].jf   = 9;
2388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    bpfRun[2].k    = Eth_PPPOE_Discovery;
2398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    {
2418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project      struct bpf_insn bpfInsn[sizeof(bpfRun) / sizeof(bpfRun[0])];
2428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project      struct bpf_program bpfProgram;
2438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project      memcpy(bpfInsn, bpfRun, sizeof(bpfRun));
2448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project      bpfInsn[PPPOE_BCAST_CMPW].k = ((0xff << 24) | (0xff << 16) |
2458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                                     (0xff << 8) | 0xff);
2468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project      bpfInsn[PPPOE_BCAST_CMPH].k = ((0xff << 8) | 0xff);
2478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project      bpfInsn[PPPOE_FILTER_CMPW].k = ((hwaddr[0] << 24) | (hwaddr[1] << 16) |
2488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project				      (hwaddr[2] << 8) | hwaddr[3]);
2498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project      bpfInsn[PPPOE_FILTER_CMPH].k = ((hwaddr[4] << 8) | hwaddr[5]);
2508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project      bpfProgram.bf_len = (sizeof(bpfInsn) / sizeof(bpfInsn[0]));
2518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project      bpfProgram.bf_insns = &bpfInsn[0];
2528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project      /* Apply the filter */
2548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project      if (ioctl(fd, BIOCSETF, &bpfProgram) < 0) {
2558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fatalSys("ioctl(BIOCSETF)");
2568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project      }
2578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
2588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
2598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/**********************************************************************
2618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%FUNCTION: openInterface
2628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%ARGUMENTS:
2638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* ifname -- name of interface
2648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* type -- Ethernet frame type (0 for any frame type)
2658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* hwaddr -- if non-NULL, set to the hardware address
2668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%RETURNS:
2678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* A file descriptor for talking with the Ethernet card.  Exits on error.
2688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Note that the Linux version of this routine returns a socket instead.
2698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%DESCRIPTION:
2708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Opens a BPF on an interface for all PPPoE traffic (discovery and
2718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* session).  If 'type' is 0, uses promiscuous mode to watch any PPPoE
2728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* traffic on this network.
2738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
2748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectint
2758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectopenInterface(char const *ifname, UINT16_t type, unsigned char *hwaddr)
2768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
2778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    static int fd = -1;
2788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    char bpfName[32];
2798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    u_int optval;
2808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    struct bpf_version bpf_ver;
2818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    struct ifreq ifr;
2828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    int sock;
2838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    int i;
2848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* BSD only opens one socket for both Discovery and Session packets */
2868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (fd >= 0) {
2878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return fd;
2888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
2898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Find a free BPF device */
2918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    for (i = 0; i < 256; i++) {
2928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	sprintf(bpfName, "/dev/bpf%d", i);
2938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (((fd = open(bpfName, O_RDWR, 0)) >= 0) ||
2948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    (errno != EBUSY)) {
2958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    break;
2968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
2978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
2988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (fd < 0) {
2998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	switch (errno) {
3008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	case EACCES:		/* permission denied */
3018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    {
3028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		char buffer[256];
3038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		sprintf(buffer, "Cannot open %.32s -- pppoe must be run as root.", bpfName);
3048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		rp_fatal(buffer);
3058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    }
3068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    break;
3078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	case EBUSY:
3088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	case ENOENT:		/* no such file */
3098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    if (i == 0) {
3108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		rp_fatal("No /dev/bpf* devices (check your kernel configuration for BPF support)");
3118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    } else {
3128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		rp_fatal("All /dev/bpf* devices are in use");
3138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    }
3148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    break;
3158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
3168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fatalSys(bpfName);
3178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
3188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if ((sock = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0) {
3208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fatalSys("socket");
3218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
3228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Check that the interface is up */
3248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
3258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
3268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fatalSys("ioctl(SIOCGIFFLAGS)");
3278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
3288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if ((ifr.ifr_flags & IFF_UP) == 0) {
3298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	char buffer[256];
3308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	sprintf(buffer, "Interface %.16s is not up\n", ifname);
3318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	rp_fatal(buffer);
3328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
3338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Fill in hardware address and initialize the packet filter rules */
3358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (hwaddr == NULL) {
3368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	rp_fatal("openInterface: no hwaddr arg.");
3378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
3388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    getHWaddr(sock, ifname, hwaddr);
3398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    initFilter(fd, type, hwaddr);
3408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Sanity check on MTU -- apparently does not work on OpenBSD */
3428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#if !defined(__OpenBSD__)
3438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
3448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (ioctl(sock, SIOCGIFMTU, &ifr) < 0) {
3458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fatalSys("ioctl(SIOCGIFMTU)");
3468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
3478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (ifr.ifr_mtu < ETH_DATA_LEN) {
3488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	char buffer[256];
3498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	sprintf(buffer, "Interface %.16s has MTU of %d -- should be %d.  You may have serious connection problems.",
3508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		ifname, ifr.ifr_mtu, ETH_DATA_LEN);
3518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	printErr(buffer);
3528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
3538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
3548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* done with the socket */
3568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (close(sock) < 0) {
3578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fatalSys("close");
3588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
3598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Check the BPF version number */
3618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (ioctl(fd, BIOCVERSION, &bpf_ver) < 0) {
3628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fatalSys("ioctl(BIOCVERSION)");
3638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
3648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if ((bpf_ver.bv_major != BPF_MAJOR_VERSION) ||
3658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        (bpf_ver.bv_minor < BPF_MINOR_VERSION)) {
3668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	char buffer[256];
3678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	sprintf(buffer, "Unsupported BPF version: %d.%d (kernel: %d.%d)",
3688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			BPF_MAJOR_VERSION, BPF_MINOR_VERSION,
3698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			bpf_ver.bv_major, bpf_ver.bv_minor);
3708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	rp_fatal(buffer);
3718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
3728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* allocate a receive packet buffer */
3748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (ioctl(fd, BIOCGBLEN, &bpfLength) < 0) {
3758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fatalSys("ioctl(BIOCGBLEN)");
3768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
3778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (!(bpfBuffer = (unsigned char *) malloc(bpfLength))) {
3788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	rp_fatal("malloc");
3798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
3808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* reads should return as soon as there is a packet available */
3828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    optval = 1;
3838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (ioctl(fd, BIOCIMMEDIATE, &optval) < 0) {
3848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fatalSys("ioctl(BIOCIMMEDIATE)");
3858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
3868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Bind the interface to the filter */
3888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
3898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (ioctl(fd, BIOCSETIF, &ifr) < 0) {
3908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	char buffer[256];
3918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	sprintf(buffer, "ioctl(BIOCSETIF) can't select interface %.16s",
3928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		ifname);
3938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	rp_fatal(buffer);
3948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
3958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    syslog(LOG_INFO, "Interface=%.16s HWaddr=%02X:%02X:%02X:%02X:%02X:%02X Device=%.32s Buffer size=%d",
3978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	   ifname,
3988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	   hwaddr[0], hwaddr[1], hwaddr[2],
3998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	   hwaddr[3], hwaddr[4], hwaddr[5],
4008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	   bpfName, bpfLength);
4018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    return fd;
4028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
4038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif /* USE_BPF */
4058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef USE_LINUX_PACKET
4078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/**********************************************************************
4088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%FUNCTION: openInterface
4098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%ARGUMENTS:
4108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* ifname -- name of interface
4118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* type -- Ethernet frame type
4128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* hwaddr -- if non-NULL, set to the hardware address
4138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%RETURNS:
4148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* A raw socket for talking to the Ethernet card.  Exits on error.
4158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%DESCRIPTION:
4168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Opens a raw Ethernet socket
4178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
4188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectint
4198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectopenInterface(char const *ifname, UINT16_t type, unsigned char *hwaddr)
4208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
4218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    int optval=1;
4228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    int fd;
4238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    struct ifreq ifr;
4248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    int domain, stype;
4258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef HAVE_STRUCT_SOCKADDR_LL
4278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    struct sockaddr_ll sa;
4288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#else
4298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    struct sockaddr sa;
4308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
4318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    memset(&sa, 0, sizeof(sa));
4338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef HAVE_STRUCT_SOCKADDR_LL
4358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    domain = PF_PACKET;
4368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    stype = SOCK_RAW;
4378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#else
4388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    domain = PF_INET;
4398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    stype = SOCK_PACKET;
4408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
4418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if ((fd = socket(domain, stype, htons(type))) < 0) {
4438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* Give a more helpful message for the common error case */
4448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (errno == EPERM) {
4458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    rp_fatal("Cannot create raw socket -- pppoe must be run as root.");
4468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
4478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fatalSys("socket");
4488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
4498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) < 0) {
4518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fatalSys("setsockopt");
4528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
4538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Fill in hardware address */
4558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (hwaddr) {
4568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
4578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
4588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    fatalSys("ioctl(SIOCGIFHWADDR)");
4598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
4608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
4618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef ARPHRD_ETHER
4628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
4638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    char buffer[256];
4648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    sprintf(buffer, "Interface %.16s is not Ethernet", ifname);
4658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    rp_fatal(buffer);
4668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
4678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
4688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (NOT_UNICAST(hwaddr)) {
4698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    char buffer[256];
4708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    sprintf(buffer,
4718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    "Interface %.16s has broadcast/multicast MAC address??",
4728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    ifname);
4738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    rp_fatal(buffer);
4748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
4758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
4768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Sanity check on MTU */
4788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
4798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (ioctl(fd, SIOCGIFMTU, &ifr) < 0) {
4808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fatalSys("ioctl(SIOCGIFMTU)");
4818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
4828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (ifr.ifr_mtu < ETH_DATA_LEN) {
4838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	char buffer[256];
4848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	sprintf(buffer, "Interface %.16s has MTU of %d -- should be %d.  You may have serious connection problems.",
4858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		ifname, ifr.ifr_mtu, ETH_DATA_LEN);
4868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	printErr(buffer);
4878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
4888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef HAVE_STRUCT_SOCKADDR_LL
4908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Get interface index */
4918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    sa.sll_family = AF_PACKET;
4928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    sa.sll_protocol = htons(type);
4938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
4958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
4968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fatalSys("ioctl(SIOCFIGINDEX): Could not get interface index");
4978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
4988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    sa.sll_ifindex = ifr.ifr_ifindex;
4998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#else
5018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    strcpy(sa.sa_data, ifname);
5028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
5038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* We're only interested in packets on specified interface */
5058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
5068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fatalSys("bind");
5078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
5088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    return fd;
5108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
5118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif /* USE_LINUX */
5138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/***********************************************************************
5158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%FUNCTION: sendPacket
5168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%ARGUMENTS:
5178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* sock -- socket to send to
5188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* pkt -- the packet to transmit
5198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* size -- size of packet (in bytes)
5208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%RETURNS:
5218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* 0 on success; -1 on failure
5228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%DESCRIPTION:
5238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Transmits a packet
5248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
5258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectint
5268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectsendPacket(PPPoEConnection *conn, int sock, PPPoEPacket *pkt, int size)
5278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
5288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#if defined(USE_BPF)
5298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (write(sock, pkt, size) < 0) {
5308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	sysErr("write (sendPacket)");
5318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return -1;
5328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
5338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#elif defined(HAVE_STRUCT_SOCKADDR_LL)
5348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (send(sock, pkt, size, 0) < 0) {
5358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	sysErr("send (sendPacket)");
5368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return -1;
5378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
5388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#else
5398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef USE_DLPI
5408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#define ABS(x)          ((x) < 0 ? -(x) : (x))
5428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	u_char  addr[MAXDLADDR];
5448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	u_char  phys[MAXDLADDR];
5458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	u_char  sap[MAXDLADDR];
5468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	u_char    xmitbuf[MAXDLBUF];
5478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int	data_size;
5488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	short	tmp_sap;
5508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	tmp_sap = htons(pkt->ethHdr.h_proto);
5528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	data_size = size - sizeof(struct ethhdr);
5538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memcpy((char *)phys, (char *)pkt->ethHdr.h_dest, ETHERADDRL);
5558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memcpy((char *)sap,  (char *)&tmp_sap, sizeof(ushort_t));
5568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memcpy((char *)xmitbuf, (char *)pkt + sizeof(struct ethhdr), data_size);
5578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (dl_saplen > 0) {  /* order is sap+phys */
5598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		(void) memcpy((char*)addr, (char*)&sap, dl_abssaplen);
5608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		(void) memcpy((char*)addr+dl_abssaplen, (char*)phys, ETHERADDRL);
5618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	} else {        /* order is phys+sap */
5628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		(void) memcpy((char*)addr, (char*)phys, ETHERADDRL);
5638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		(void) memcpy((char*)addr+ETHERADDRL, (char*)&sap, dl_abssaplen);
5648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
5658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef DL_DEBUG
5678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	printf("%02x:%02x:%02x:%02x:%02x:%02x %02x:%02x\n",
5688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		addr[0],addr[1],addr[2],addr[3],addr[4],addr[5],
5698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		addr[6],addr[7]);
5708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
5718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	dlunitdatareq(sock, addr, dl_addrlen, 0, 0, xmitbuf, data_size);
5738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#else
5778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    struct sockaddr sa;
5788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (!conn) {
5808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	rp_fatal("relay and server not supported on Linux 2.0 kernels");
5818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
5828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    strcpy(sa.sa_data, conn->ifName);
5838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (sendto(sock, pkt, size, 0, &sa, sizeof(sa)) < 0) {
5848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	sysErr("sendto (sendPacket)");
5858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return -1;
5868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
5878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
5888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
5898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    return 0;
5908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
5918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef USE_BPF
5938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/***********************************************************************
5948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%FUNCTION: clearPacketHeader
5958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%ARGUMENTS:
5968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* pkt -- packet that needs its head clearing
5978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%RETURNS:
5988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* nothing
5998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%DESCRIPTION:
6008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Clears a PPPoE packet header after a truncated packet has been
6018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* received.  Insures that the packet will fail any integrity tests
6028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* and will be discarded by upper level routines.  Also resets the
6038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* bpfSize and bpfOffset variables to force a new read on the next
6048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* call to receivePacket().
6058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
6068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid
6078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectclearPacketHeader(PPPoEPacket *pkt)
6088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
6098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    bpfSize = bpfOffset = 0;
6108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    memset(pkt, 0, HDR_SIZE);
6118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
6128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
6138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
6148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/***********************************************************************
6158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%FUNCTION: receivePacket
6168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%ARGUMENTS:
6178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* sock -- socket to read from
6188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* pkt -- place to store the received packet
6198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* size -- set to size of packet in bytes
6208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%RETURNS:
6218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* >= 0 if all OK; < 0 if error
6228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%DESCRIPTION:
6238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Receives a packet
6248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
6258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectint
6268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectreceivePacket(int sock, PPPoEPacket *pkt, int *size)
6278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
6288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef USE_BPF
6298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    struct bpf_hdr hdr;
6308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    int seglen, copylen;
6318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
6328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (bpfSize <= 0) {
6338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	bpfOffset = 0;
6348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if ((bpfSize = read(sock, bpfBuffer, bpfLength)) < 0) {
6358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    sysErr("read (receivePacket)");
6368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    return -1;
6378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
6388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
6398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (bpfSize < sizeof(hdr)) {
6408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	syslog(LOG_ERR, "Truncated bpf packet header: len=%d", bpfSize);
6418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	clearPacketHeader(pkt);		/* resets bpfSize and bpfOffset */
6428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return 0;
6438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
6448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    memcpy(&hdr, bpfBuffer + bpfOffset, sizeof(hdr));
6458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (hdr.bh_caplen != hdr.bh_datalen) {
6468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	syslog(LOG_ERR, "Truncated bpf packet: caplen=%d, datalen=%d",
6478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	       hdr.bh_caplen, hdr.bh_datalen);
6488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	clearPacketHeader(pkt);		/* resets bpfSize and bpfOffset */
6498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return 0;
6508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
6518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    seglen = hdr.bh_hdrlen + hdr.bh_caplen;
6528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (seglen > bpfSize) {
6538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	syslog(LOG_ERR, "Truncated bpf packet: seglen=%d, bpfSize=%d",
6548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	       seglen, bpfSize);
6558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	clearPacketHeader(pkt);		/* resets bpfSize and bpfOffset */
6568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return 0;
6578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
6588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    seglen = BPF_WORDALIGN(seglen);
6598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    *size = copylen = ((hdr.bh_caplen < sizeof(PPPoEPacket)) ?
6608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			hdr.bh_caplen : sizeof(PPPoEPacket));
6618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    memcpy(pkt, bpfBuffer + bpfOffset + hdr.bh_hdrlen, copylen);
6628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (seglen >= bpfSize) {
6638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	bpfSize = bpfOffset = 0;
6648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    } else {
6658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	bpfSize -= seglen;
6668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	bpfOffset += seglen;
6678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
6688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#else
6698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef USE_DLPI
6708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	struct strbuf data;
6718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int flags = 0;
6728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int retval;
6738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
6748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	data.buf = (char *) pkt;
6758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	data.maxlen = MAXDLBUF;
6768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	data.len = 0;
6778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
6788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if ((retval = getmsg(sock, NULL, &data, &flags)) < 0) {
6798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    sysErr("read (receivePacket)");
6808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    return -1;
6818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
6828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
6838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	*size = data.len;
6848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
6858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#else
6868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if ((*size = recv(sock, pkt, sizeof(PPPoEPacket), 0)) < 0) {
6878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	sysErr("recv (receivePacket)");
6888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return -1;
6898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
6908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
6918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
6928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    return 0;
6938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
6948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
6958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef USE_DLPI
6968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/**********************************************************************
6978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%FUNCTION: openInterface
6988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%ARGUMENTS:
6998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* ifname -- name of interface
7008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* type -- Ethernet frame type
7018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* hwaddr -- if non-NULL, set to the hardware address
7028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%RETURNS:
7038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* A raw socket for talking to the Ethernet card.  Exits on error.
7048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%DESCRIPTION:
7058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Opens a raw Ethernet socket
7068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
7078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectint
7088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectopenInterface(char const *ifname, UINT16_t type, unsigned char *hwaddr)
7098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
7108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    int fd;
7118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    long buf[MAXDLBUF];
7128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
7138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	union   DL_primitives   *dlp;
7148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
7158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    char base_dev[PATH_MAX];
7168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    int ppa;
7178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
7188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if(strlen(ifname) > PATH_MAX) {
7198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	rp_fatal("socket: string to long");
7208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
7218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
7228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    ppa = atoi(&ifname[strlen(ifname)-1]);
7238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    strncpy(base_dev, ifname, PATH_MAX);
7248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    base_dev[strlen(base_dev)-1] = '\0';
7258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
7268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/* rearranged order of DLPI code - delphys 20010803 */
7278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    dlp = (union DL_primitives*) buf;
7288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
7298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (( fd = open(base_dev, O_RDWR)) < 0) {
7308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* Give a more helpful message for the common error case */
7318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (errno == EPERM) {
7328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    rp_fatal("Cannot create raw socket -- pppoe must be run as root.");
7338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
7348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fatalSys("socket");
7358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
7368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
7378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/* rearranged order of DLPI code - delphys 20010803 */
7388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    dlattachreq(fd, ppa);
7398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    dlokack(fd, (char *)buf);
7408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
7418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    dlbindreq(fd, type, 0, DL_CLDLS, 0, 0);
7428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    dlbindack(fd, (char *)buf);
7438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
7448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    dlinforeq(fd);
7458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    dlinfoack(fd, (char *)buf);
7468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
7478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    dl_abssaplen = ABS(dlp->info_ack.dl_sap_length);
7488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    dl_saplen = dlp->info_ack.dl_sap_length;
7498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (ETHERADDRL != (dlp->info_ack.dl_addr_length - dl_abssaplen))
7508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fatalSys("invalid destination physical address length");
7518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    dl_addrlen = dl_abssaplen + ETHERADDRL;
7528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
7538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/* ethernet address retrieved as part of DL_INFO_ACK - delphys 20010803 */
7548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    memcpy(hwaddr, (u_char*)((char*)(dlp) + (int)(dlp->info_ack.dl_addr_offset)), ETHERADDRL);
7558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
7568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if ( strioctl(fd, DLIOCRAW, -1, 0, NULL) < 0 ) {
7578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fatalSys("DLIOCRAW");
7588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
7598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
7608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (ioctl(fd, I_FLUSH, FLUSHR) < 0) fatalSys("I_FLUSH");
7618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
7628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    return fd;
7638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
7648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
7658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/* cloned from dlcommon.c */
7668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
7678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid dlpromisconreq(int fd, u_long level)
7688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
7698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        dl_promiscon_req_t      promiscon_req;
7708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        struct  strbuf  ctl;
7718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        int     flags;
7728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
7738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        promiscon_req.dl_primitive = DL_PROMISCON_REQ;
7748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        promiscon_req.dl_level = level;
7758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
7768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        ctl.maxlen = 0;
7778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        ctl.len = sizeof (promiscon_req);
7788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        ctl.buf = (char *) &promiscon_req;
7798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
7808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        flags = 0;
7818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
7828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
7838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                fatalSys("dlpromiscon:  putmsg");
7848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
7858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
7868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
7878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid dlinforeq(int fd)
7888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
7898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        dl_info_req_t   info_req;
7908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        struct  strbuf  ctl;
7918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        int     flags;
7928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
7938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        info_req.dl_primitive = DL_INFO_REQ;
7948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
7958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        ctl.maxlen = 0;
7968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        ctl.len = sizeof (info_req);
7978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        ctl.buf = (char *) &info_req;
7988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
7998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        flags = RS_HIPRI;
8008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
8018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
8028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                fatalSys("dlinforeq:  putmsg");
8038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
8048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
8058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid dlunitdatareq(int fd, u_char *addrp, int addrlen, u_long minpri, u_long maxpri, u_char *datap, int datalen)
8068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
8078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        long    buf[MAXDLBUF];
8088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        union   DL_primitives   *dlp;
8098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        struct  strbuf  data, ctl;
8108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
8118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        dlp = (union DL_primitives*) buf;
8128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
8138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        dlp->unitdata_req.dl_primitive = DL_UNITDATA_REQ;
8148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        dlp->unitdata_req.dl_dest_addr_length = addrlen;
8158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        dlp->unitdata_req.dl_dest_addr_offset = sizeof (dl_unitdata_req_t);
8168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        dlp->unitdata_req.dl_priority.dl_min = minpri;
8178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        dlp->unitdata_req.dl_priority.dl_max = maxpri;
8188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
8198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        (void) memcpy(OFFADDR(dlp, sizeof (dl_unitdata_req_t)), addrp, addrlen);
8208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
8218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        ctl.maxlen = 0;
8228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        ctl.len = sizeof (dl_unitdata_req_t) + addrlen;
8238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        ctl.buf = (char *) buf;
8248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
8258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        data.maxlen = 0;
8268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        data.len = datalen;
8278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        data.buf = (char *) datap;
8288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
8298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        if (putmsg(fd, &ctl, &data, 0) < 0)
8308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                fatalSys("dlunitdatareq:  putmsg");
8318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
8328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
8338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid dlinfoack(int fd, char *bufp)
8348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
8358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        union   DL_primitives   *dlp;
8368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        struct  strbuf  ctl;
8378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        int     flags;
8388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
8398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        ctl.maxlen = MAXDLBUF;
8408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        ctl.len = 0;
8418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        ctl.buf = bufp;
8428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
8438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlinfoack");
8448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
8458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        dlp = (union DL_primitives *) ctl.buf;
8468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
8478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        expecting(DL_INFO_ACK, dlp);
8488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
8498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        if (ctl.len < sizeof (dl_info_ack_t)) {
8508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		char buffer[256];
8518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		sprintf(buffer, "dlinfoack:  response ctl.len too short:  %d", ctl.len);
8528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                rp_fatal(buffer);
8538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
8548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
8558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        if (flags != RS_HIPRI)
8568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                rp_fatal("dlinfoack:  DL_INFO_ACK was not M_PCPROTO");
8578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
8588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        if (ctl.len < sizeof (dl_info_ack_t)) {
8598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		char buffer[256];
8608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		sprintf(buffer, "dlinfoack:  short response ctl.len:  %d", ctl.len);
8618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		rp_fatal(buffer);
8628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
8638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
8648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
8658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid dlbindreq(int fd, u_long sap, u_long max_conind, u_long service_mode, u_long conn_mgmt, u_long xidtest)
8668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
8678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        dl_bind_req_t   bind_req;
8688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        struct  strbuf  ctl;
8698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        int     flags;
8708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
8718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        bind_req.dl_primitive = DL_BIND_REQ;
8728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        bind_req.dl_sap = sap;
8738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        bind_req.dl_max_conind = max_conind;
8748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        bind_req.dl_service_mode = service_mode;
8758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        bind_req.dl_conn_mgmt = conn_mgmt;
8768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        bind_req.dl_xidtest_flg = xidtest;
8778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
8788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        ctl.maxlen = 0;
8798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        ctl.len = sizeof (bind_req);
8808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        ctl.buf = (char *) &bind_req;
8818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
8828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        flags = 0;
8838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
8848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
8858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                fatalSys("dlbindreq:  putmsg");
8868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
8878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
8888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid dlattachreq(int fd, u_long ppa)
8898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
8908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        dl_attach_req_t attach_req;
8918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        struct  strbuf  ctl;
8928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        int     flags;
8938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
8948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        attach_req.dl_primitive = DL_ATTACH_REQ;
8958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        attach_req.dl_ppa = ppa;
8968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
8978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        ctl.maxlen = 0;
8988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        ctl.len = sizeof (attach_req);
8998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        ctl.buf = (char *) &attach_req;
9008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
9018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        flags = 0;
9028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
9038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
9048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                fatalSys("dlattachreq:  putmsg");
9058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
9068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
9078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid dlokack(int fd, char *bufp)
9088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
9098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        union   DL_primitives   *dlp;
9108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        struct  strbuf  ctl;
9118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        int     flags;
9128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
9138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        ctl.maxlen = MAXDLBUF;
9148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        ctl.len = 0;
9158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        ctl.buf = bufp;
9168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
9178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlokack");
9188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
9198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        dlp = (union DL_primitives *) ctl.buf;
9208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
9218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        expecting(DL_OK_ACK, dlp);
9228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
9238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        if (ctl.len < sizeof (dl_ok_ack_t)) {
9248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		char buffer[256];
9258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		sprintf(buffer, "dlokack:  response ctl.len too short:  %d", ctl.len);
9268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		rp_fatal(buffer);
9278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
9288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
9298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        if (flags != RS_HIPRI)
9308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                rp_fatal("dlokack:  DL_OK_ACK was not M_PCPROTO");
9318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
9328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        if (ctl.len < sizeof (dl_ok_ack_t)) {
9338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		char buffer[256];
9348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		sprintf(buffer, "dlokack:  short response ctl.len:  %d", ctl.len);
9358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		rp_fatal(buffer);
9368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
9378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
9388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
9398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid dlbindack(int fd, char *bufp)
9408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
9418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        union   DL_primitives   *dlp;
9428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        struct  strbuf  ctl;
9438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        int     flags;
9448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
9458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        ctl.maxlen = MAXDLBUF;
9468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        ctl.len = 0;
9478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        ctl.buf = bufp;
9488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
9498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlbindack");
9508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
9518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        dlp = (union DL_primitives *) ctl.buf;
9528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
9538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        expecting(DL_BIND_ACK, dlp);
9548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
9558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        if (flags != RS_HIPRI)
9568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                rp_fatal("dlbindack:  DL_OK_ACK was not M_PCPROTO");
9578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
9588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        if (ctl.len < sizeof (dl_bind_ack_t)) {
9598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		char buffer[256];
9608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		sprintf(buffer, "dlbindack:  short response ctl.len:  %d", ctl.len);
9618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		rp_fatal(buffer);
9628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
9638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
9648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
9658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectint strioctl(int fd, int cmd, int timout, int len, char *dp)
9668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
9678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        struct  strioctl        sioc;
9688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        int     rc;
9698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
9708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        sioc.ic_cmd = cmd;
9718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        sioc.ic_timout = timout;
9728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        sioc.ic_len = len;
9738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        sioc.ic_dp = dp;
9748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        rc = ioctl(fd, I_STR, &sioc);
9758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
9768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        if (rc < 0)
9778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                return (rc);
9788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        else
9798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                return (sioc.ic_len);
9808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
9818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
9828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid strgetmsg(int fd, struct strbuf *ctlp, struct strbuf *datap, int *flagsp, char *caller)
9838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
9848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        int     rc;
9858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        static  char    errmsg[80];
9868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
9878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        /*
9888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project         * Start timer.
9898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project         */
9908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        (void) signal(SIGALRM, sigalrm);
9918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        if (alarm(MAXWAIT) < 0) {
9928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                (void) sprintf(errmsg, "%s:  alarm", caller);
9938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                fatalSys(errmsg);
9948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        }
9958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
9968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        /*
9978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project         * Set flags argument and issue getmsg().
9988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project         */
9998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        *flagsp = 0;
10008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        if ((rc = getmsg(fd, ctlp, datap, flagsp)) < 0) {
10018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                (void) sprintf(errmsg, "%s:  getmsg", caller);
10028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                fatalSys(errmsg);
10038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        }
10048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
10058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        /*
10068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project         * Stop timer.
10078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project         */
10088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        if (alarm(0) < 0) {
10098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                (void) sprintf(errmsg, "%s:  alarm", caller);
10108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                fatalSys(errmsg);
10118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        }
10128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
10138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        /*
10148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project         * Check for MOREDATA and/or MORECTL.
10158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project         */
10168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        if ((rc & (MORECTL | MOREDATA)) == (MORECTL | MOREDATA)) {
10178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		char buffer[256];
10188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		sprintf(buffer, "%s:  MORECTL|MOREDATA", caller);
10198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		rp_fatal(buffer);
10208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
10218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
10228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        if (rc & MORECTL) {
10238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		char buffer[256];
10248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		sprintf(buffer, "%s:  MORECTL", caller);
10258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		rp_fatal(buffer);
10268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
10278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
10288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        if (rc & MOREDATA) {
10298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		char buffer[256];
10308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		sprintf(buffer, "%s:  MOREDATA", caller);
10318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		rp_fatal(buffer);
10328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
10338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
10348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        /*
10358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project         * Check for at least sizeof (long) control data portion.
10368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project         */
10378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        if (ctlp->len < sizeof (long)) {
10388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		char buffer[256];
10398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		sprintf(buffer, "getmsg:  control portion length < sizeof (long):  %d", ctlp->len);
10408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		rp_fatal(buffer);
10418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
10428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
10438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
10448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid sigalrm(int sig)
10458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
10468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        (void) rp_fatal("sigalrm:  TIMEOUT");
10478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
10488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
10498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid expecting(int prim, union DL_primitives *dlp)
10508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
10518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        if (dlp->dl_primitive != (u_long)prim) {
10528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		char buffer[256];
10538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		sprintf(buffer, "expected %s got %s", dlprim(prim), dlprim(dlp->dl_primitive));
10548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		rp_fatal(buffer);
10558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		exit(1);
10568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
10578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
10588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
10598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectchar *dlprim(u_long prim)
10608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
10618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        static  char    primbuf[80];
10628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
10638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        switch ((int)prim) {
10648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_INFO_REQ);
10658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_INFO_ACK);
10668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_ATTACH_REQ);
10678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_DETACH_REQ);
10688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_BIND_REQ);
10698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_BIND_ACK);
10708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_UNBIND_REQ);
10718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_OK_ACK);
10728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_ERROR_ACK);
10738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_SUBS_BIND_REQ);
10748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_SUBS_BIND_ACK);
10758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_UNITDATA_REQ);
10768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_UNITDATA_IND);
10778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_UDERROR_IND);
10788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_UDQOS_REQ);
10798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_CONNECT_REQ);
10808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_CONNECT_IND);
10818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_CONNECT_RES);
10828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_CONNECT_CON);
10838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_TOKEN_REQ);
10848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_TOKEN_ACK);
10858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_DISCONNECT_REQ);
10868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_DISCONNECT_IND);
10878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_RESET_REQ);
10888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_RESET_IND);
10898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_RESET_RES);
10908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                CASERET(DL_RESET_CON);
10918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                default:
10928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                        (void) sprintf(primbuf, "unknown primitive 0x%lx", prim);
10938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project                        return (primbuf);
10948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        }
10958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
10968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
10978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif /* USE_DLPI */
1098