http://gimel.esc.cam.ac.uk/james/rpld/src/rpld-1.4.tar.gz
[rpld.git] / linux-ps.c
1 /*************************************************
2 *     rpld - an IBM style RIPL server            *
3 *************************************************/
4
5 /* Copyright (c) 1999,2000, James McKenzie.
6  *                      All rights reserved
7  * Copyright (c) 1998,2000, Christopher Lightfoot.
8  *                      All rights reserved
9  *
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.
13  *
14  * IBM is a trademark of IBM corp.
15  *
16  */
17
18
19 static char rcsid[] = "$Id: linux-ps.c,v 1.8 2000/07/16 14:24:16 root Exp $";
20
21 /* 
22  * $Log: linux-ps.c,v $
23  * Revision 1.8  2000/07/16 14:24:16  root
24  * #
25  *
26  * Revision 1.7  2000/07/16 14:05:28  root
27  * #
28  *
29  * Revision 1.6  2000/07/16 13:18:10  root
30  * #
31  *
32  * Revision 1.1  2000/07/16 13:16:33  root
33  * #
34  *
35  * Revision 1.5  1999/09/13 11:17:35  root
36  * \#
37  *
38  * Revision 1.4  1999/09/11 16:52:15  root
39  * \#
40  *
41  * Revision 1.3  1999/09/11 16:34:50  root
42  * \#
43  *
44  * Revision 1.2  1999/09/10 22:06:43  root
45  * \#
46  *
47  * Revision 1.1  1999/09/10 17:32:26  root
48  * \#
49  *
50  * Revision 1.1  1999/05/17 21:53:33  root
51  * Initial revision
52  *
53  */
54
55 /*
56  * CAUTION THIS CODE COMES WITH NO WARARNTY IT IS COPYRIGHT 1999 BY
57  * James McKenzie All rights reserved. GPL applies
58  */
59
60
61 #include "project.h"
62
63 #undef __GLIBC__
64 #include <linux/socket.h>
65 #include <linux/if_ether.h>
66 #include <linux/if_arp.h>
67 #include <linux/if_packet.h>
68 #include <linux/route.h>
69 #define __GLIBC__
70
71
72
73 static void
74 get_hwaddr (unsigned char *name, unsigned char *addr)
75 {
76   struct ifreq ifr;
77   int fd = socket (AF_INET, SOCK_DGRAM, 0);
78
79   if (fd < 0)
80     {
81       syslog (LOG_ERR, "socket:%m");
82       return;
83     }
84   bcopy (name, &ifr.ifr_name, sizeof (ifr.ifr_name));
85
86
87   /* find my own hardware address */
88   if (ioctl (fd, SIOCGIFHWADDR, &ifr) < 0)
89     {
90       close (fd);
91       syslog (LOG_ERR, "ioctl(SIOCGIFHWADDR):%m");
92       exit (-1);
93     }
94   close (fd);
95
96
97   bcopy (&ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN);
98
99 }
100
101 void
102 nit_close (struct nit *n)
103 {
104   if (!n)
105     return;
106
107   close (n->fd);
108   free (n->name);
109
110 /*FIXME: we should demulticast at this point but we need to have some 
111  *mechanism for detecting if anyone else wants it
112  */
113
114   free (n);
115 }
116
117 struct nit *
118 nit_open (char *name)
119 {
120   struct nit *n;
121   struct sockaddr sa;
122   int fd;
123
124   if (!name)
125     name = "eth0";
126
127 #ifdef PF_PACKET
128   fd = socket (PF_PACKET, SOCK_PACKET, htons (ETH_P_ALL));
129
130   if (fd < 0)
131 #endif
132     fd = socket (AF_INET, SOCK_PACKET, htons (ETH_P_ALL));
133
134   if (fd < 0)
135     {
136       syslog (LOG_ERR, "socket:%m");
137       return (NULL);
138     }
139
140   bzero (&sa, sizeof (sa));
141   sa.sa_family = AF_INET;
142   memcpy (&sa.sa_data, name, sizeof (sa.sa_data));
143
144   if (bind (fd, &sa, sizeof (sa)) < 0)
145     {
146       close (fd);
147       syslog (LOG_ERR, "bind:%m");
148       return (NULL);
149     }
150
151
152   n = (struct nit *) malloc (sizeof (struct nit));
153
154   n->fd = fd;
155   n->name = (char *) malloc (MAX_NAME_LEN);
156   bzero (n->name, MAX_NAME_LEN);
157
158   strcpy (n->name, name);
159   get_hwaddr (n->name, n->mac);
160
161   return (n);
162 }
163
164 void
165 nit_send_frame (struct nit *n, unsigned char *frame, int len)
166 {
167   struct sockaddr sa;
168   struct msghdr msg;
169   struct iovec iov;
170
171   bzero (&msg, sizeof (msg));
172   bzero (&sa, sizeof (sa));
173
174   sa.sa_family = AF_INET;
175   strncpy (sa.sa_data, n->name, sizeof (sa.sa_data));
176
177   if (sendto (n->fd, frame, len, 0, &sa, sizeof (sa)) < 0)
178     syslog (LOG_ERR, "sendto: %m");
179
180   return;
181
182 }
183
184
185 void
186 nit_multicast (struct nit *n, unsigned char *mcaddr)
187 {
188   struct ifreq ifr;
189   int fd = socket (AF_INET, SOCK_DGRAM, 0);
190
191   strncpy (ifr.ifr_name, n->name, sizeof (ifr.ifr_name));
192
193   ifr.ifr_hwaddr.sa_family = AF_UNSPEC;
194
195   bcopy (mcaddr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
196
197   if (ioctl (fd, SIOCADDMULTI, &ifr) < 0)
198     {
199       close (fd);
200       syslog (LOG_ERR, "ioctl(SIOCADDMULTI):%m");
201     }
202 }
203
204 int
205 nit_read_packet (struct nit *n, char *buf, int len, struct timeval *tv)
206 {
207   fd_set rfds;
208   int ret;
209
210   FD_ZERO (&rfds);
211   FD_SET (n->fd, &rfds);
212
213
214   ret = select ((n->fd) + 1, &rfds, NULL, NULL, tv);
215
216   if (ret < 0)
217     return (ret);
218
219   if (FD_ISSET ((n->fd), &rfds))
220     {
221
222       ret = read (n->fd, buf, len);
223
224       return (ret);
225     }
226   else
227     {
228       return (0);
229     }
230
231 }