1 /*************************************************
2 * rpld - an IBM style RIPL server *
3 *************************************************/
5 /* Copyright (c) 1999,2000,2001 James McKenzie.
7 * Copyright (c) 1998,2000,2001 Christopher Lightfoot.
10 * By using this file, you agree to the terms and conditions set
11 * forth in the LICENCE file which can be found at the top level of
12 * the rpld distribution.
14 * IBM is a trademark of IBM corp.
19 static char rcsid[] = "$Id: linux-nit.c,v 1.5 2001/11/01 15:26:29 root Exp $";
22 * $Log: linux-nit.c,v $
23 * Revision 1.5 2001/11/01 15:26:29 root
26 * Revision 1.4 2001/11/01 15:24:26 root
29 * Revision 1.3 2001/11/01 15:23:59 root
32 * Revision 1.2 2000/09/26 03:48:23 root
35 * Revision 1.1 2000/09/26 03:44:29 root
38 * Revision 1.8 2000/07/16 14:24:16 root
41 * Revision 1.7 2000/07/16 14:05:28 root
44 * Revision 1.6 2000/07/16 13:18:10 root
47 * Revision 1.1 2000/07/16 13:16:33 root
50 * Revision 1.5 1999/09/13 11:17:35 root
53 * Revision 1.4 1999/09/11 16:52:15 root
56 * Revision 1.3 1999/09/11 16:34:50 root
59 * Revision 1.2 1999/09/10 22:06:43 root
62 * Revision 1.1 1999/09/10 17:32:26 root
65 * Revision 1.1 1999/05/17 21:53:33 root
71 * CAUTION THIS CODE COMES WITH NO WARARNTY IT IS COPYRIGHT 1999 BY
72 * James McKenzie All rights reserved. GPL applies
80 #include <sys/socket.h>
81 #include <linux/if_ether.h>
82 #include <linux/if_arp.h>
83 #include <linux/if_packet.h>
84 #include <sys/ioctl.h>
90 #include <linux/socket.h>
91 #include <linux/if_ether.h>
92 #include <linux/if_arp.h>
93 #include <linux/if_packet.h>
94 #include <asm/socket.h>
102 unsigned char mac[ETH_ALEN];
108 get_hwaddr (char *name, unsigned char *addr)
111 int fd = socket (AF_INET, SOCK_DGRAM, 0);
115 syslog (LOG_ERR, "socket:%m");
118 bcopy (name, &ifr.ifr_name, sizeof (ifr.ifr_name));
121 /* find my own hardware address */
122 if (ioctl (fd, SIOCGIFHWADDR, &ifr) < 0)
125 syslog (LOG_ERR, "ioctl(SIOCGIFHWADDR):%m");
130 bcopy (&ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN);
135 nit_close (struct nit *n)
144 /*FIXME: we should demulticast at this point but we need to have some
145 *mechanism for detecting if anyone else wants it
152 nit_open (char *name)
155 struct sockaddr_ll sll;
159 syslog (LOG_ERR, "RPLD 802.2 LINUX-NIT support %s", rcsid);
161 fd = socket (PF_PACKET, SOCK_DGRAM, 0);
165 syslog (LOG_ERR, "socket:%m");
173 strcpy (ifr.ifr_name, name);
175 if (ioctl (fd, SIOCGIFINDEX, &ifr) < 0)
177 syslog (LOG_ERR, "SIOCGIFINDEX on %s: %m\n", name);
186 bzero (&sll, sizeof (sll));
187 sll.sll_family = AF_PACKET;
188 sll.sll_protocol = htons (ETH_P_802_2);
189 sll.sll_ifindex = ifr.ifr_ifindex;
191 if (bind (fd, (struct sockaddr *) &sll, sizeof (sll)) < 0)
194 syslog (LOG_ERR, "bind:%m");
199 n = (struct nit *) malloc (sizeof (struct nit));
201 n->index = ifr.ifr_ifindex;
205 get_hwaddr (name, n->mac);
209 n->name = strdup (name);
220 nit_mac (struct nit *n)
226 nit_send (struct nit *n, unsigned char *frame, int len, unsigned char *to)
228 struct sockaddr_ll sll;
232 bzero (&msg, sizeof (msg));
233 bzero (&sll, sizeof (sll));
236 sll.sll_family = AF_PACKET;
237 /* This is the most horrible hack you are ever likely to see*/
238 /* if you don't understand what's happening in the line below*/
239 /* be very very happy */
240 sll.sll_protocol = htons (len);
241 sll.sll_ifindex = n->index;
242 sll.sll_hatype = ARPHRD_ETHER;
243 sll.sll_pkttype = PACKET_OUTGOING;
244 sll.sll_halen = ETH_ALEN;
245 bcopy (to, &sll.sll_addr[0], ETH_ALEN);
247 if (sendto (n->fd, frame, len, 0, (struct sockaddr *) &sll, sizeof (sll)) <
250 syslog (LOG_ERR, "sendto: %m");
260 nit_multicast (struct nit *n, unsigned char *mcaddr)
263 int fd = socket (AF_INET, SOCK_DGRAM, 0);
265 strncpy (ifr.ifr_name, n->name, sizeof (ifr.ifr_name));
267 ifr.ifr_hwaddr.sa_family = AF_UNSPEC;
269 bcopy (mcaddr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
271 if (ioctl (fd, SIOCADDMULTI, &ifr) < 0)
274 syslog (LOG_ERR, "ioctl(SIOCADDMULTI):%m");
282 nit_recv (struct nit *n, unsigned char *buf, int len, unsigned char *ufrom,
287 struct sockaddr_ll from;
288 socklen_t fromlen = sizeof (from);
292 FD_SET (n->fd, &rfds);
294 ret = select ((n->fd) + 1, &rfds, NULL, NULL, tv);
299 if (FD_ISSET ((n->fd), &rfds))
302 recvfrom (n->fd, buf, len, 0, (struct sockaddr *) &from, &fromlen);
304 bcopy (from.sll_addr, ufrom, ETH_ALEN);