[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]

FreeBSD/Linux Kernel Cross Reference
sys/netipx/ipx.c

Version: -  FREEBSD  -  FREEBSD7  -  FREEBSD70  -  FREEBSD6  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  OPENSOLARIS  -  minix-3-1-1  -  TRUSTEDBSD-SEBSD  -  FREEBSD-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  excerpts  -  bigexcerpts 

  1 /*-
  2  * Copyright (c) 1984, 1985, 1986, 1987, 1993
  3  *      The Regents of the University of California.  All rights reserved.
  4  *
  5  * Redistribution and use in source and binary forms, with or without
  6  * modification, are permitted provided that the following conditions
  7  * are met:
  8  * 1. Redistributions of source code must retain the above copyright
  9  *    notice, this list of conditions and the following disclaimer.
 10  * 2. Redistributions in binary form must reproduce the above copyright
 11  *    notice, this list of conditions and the following disclaimer in the
 12  *    documentation and/or other materials provided with the distribution.
 13  * 4. Neither the name of the University nor the names of its contributors
 14  *    may be used to endorse or promote products derived from this software
 15  *    without specific prior written permission.
 16  *
 17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 27  * SUCH DAMAGE.
 28  *
 29  * Copyright (c) 1995, Mike Mitchell
 30  *
 31  * Redistribution and use in source and binary forms, with or without
 32  * modification, are permitted provided that the following conditions
 33  * are met:
 34  * 1. Redistributions of source code must retain the above copyright
 35  *    notice, this list of conditions and the following disclaimer.
 36  * 2. Redistributions in binary form must reproduce the above copyright
 37  *    notice, this list of conditions and the following disclaimer in the
 38  *    documentation and/or other materials provided with the distribution.
 39  * 3. All advertising materials mentioning features or use of this software
 40  *    must display the following acknowledgement:
 41  *      This product includes software developed by the University of
 42  *      California, Berkeley and its contributors.
 43  * 4. Neither the name of the University nor the names of its contributors
 44  *    may be used to endorse or promote products derived from this software
 45  *    without specific prior written permission.
 46  *
 47  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 48  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 49  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 50  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 51  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 52  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 53  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 54  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 55  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 56  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 57  * SUCH DAMAGE.
 58  *
 59  *      @(#)ipx.c
 60  */
 61 
 62 #include <sys/cdefs.h>
 63 __FBSDID("$FreeBSD: src/sys/netipx/ipx.c,v 1.34 2008/09/17 15:49:44 attilio Exp $");
 64 
 65 #include <sys/param.h>
 66 #include <sys/kernel.h>
 67 #include <sys/systm.h>
 68 #include <sys/malloc.h>
 69 #include <sys/priv.h>
 70 #include <sys/sockio.h>
 71 #include <sys/socket.h>
 72 
 73 #include <net/if.h>
 74 #include <net/route.h>
 75 
 76 #include <netipx/ipx.h>
 77 #include <netipx/ipx_if.h>
 78 #include <netipx/ipx_var.h>
 79 
 80 /*
 81  * XXXRW: Requires synchronization.
 82  */
 83 struct ipx_ifaddr *ipx_ifaddr;
 84 
 85 static  void ipx_ifscrub(struct ifnet *ifp, struct ipx_ifaddr *ia);
 86 static  int ipx_ifinit(struct ifnet *ifp, struct ipx_ifaddr *ia,
 87                        struct sockaddr_ipx *sipx, int scrub);
 88 
 89 /*
 90  * Generic internet control operations (ioctl's).
 91  */
 92 int
 93 ipx_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
 94     struct thread *td)
 95 {
 96         struct ifreq *ifr = (struct ifreq *)data;
 97         struct ipx_aliasreq *ifra = (struct ipx_aliasreq *)data;
 98         struct ipx_ifaddr *ia;
 99         struct ifaddr *ifa;
100         struct ipx_ifaddr *oia;
101         int dstIsNew, hostIsNew;
102         int error = 0, priv;
103 
104         /*
105          * Find address for this interface, if it exists.
106          */
107         if (ifp == NULL)
108                 return (EADDRNOTAVAIL);
109         for (ia = ipx_ifaddr; ia != NULL; ia = ia->ia_next)
110                 if (ia->ia_ifp == ifp)
111                         break;
112 
113         switch (cmd) {
114 
115         case SIOCGIFADDR:
116                 if (ia == NULL)
117                         return (EADDRNOTAVAIL);
118                 *(struct sockaddr_ipx *)&ifr->ifr_addr = ia->ia_addr;
119                 return (0);
120 
121         case SIOCGIFBRDADDR:
122                 if (ia == NULL)
123                         return (EADDRNOTAVAIL);
124                 if ((ifp->if_flags & IFF_BROADCAST) == 0)
125                         return (EINVAL);
126                 *(struct sockaddr_ipx *)&ifr->ifr_dstaddr = ia->ia_broadaddr;
127                 return (0);
128 
129         case SIOCGIFDSTADDR:
130                 if (ia == NULL)
131                         return (EADDRNOTAVAIL);
132                 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
133                         return (EINVAL);
134                 *(struct sockaddr_ipx *)&ifr->ifr_dstaddr = ia->ia_dstaddr;
135                 return (0);
136         }
137 
138         switch (cmd) {
139         case SIOCAIFADDR:
140         case SIOCDIFADDR:
141                 priv = (cmd == SIOCAIFADDR) ? PRIV_NET_ADDIFADDR :
142                     PRIV_NET_DELIFADDR;
143                 if (td && (error = priv_check(td, priv)) != 0)
144                         return (error);
145                 if (ifra->ifra_addr.sipx_family == AF_IPX)
146                     for (oia = ia; ia != NULL; ia = ia->ia_next) {
147                         if (ia->ia_ifp == ifp  &&
148                             ipx_neteq(ia->ia_addr.sipx_addr,
149                                   ifra->ifra_addr.sipx_addr))
150                             break;
151                     }
152                 if (cmd == SIOCDIFADDR && ia == NULL)
153                         return (EADDRNOTAVAIL);
154                 /* FALLTHROUGH */
155 
156         case SIOCSIFADDR:
157         case SIOCSIFDSTADDR:
158                 if (td && (error = priv_check(td, PRIV_NET_SETLLADDR)) != 0)
159                         return (error);
160                 if (ia == NULL) {
161                         oia = (struct ipx_ifaddr *)
162                                 malloc(sizeof(*ia), M_IFADDR,
163                                 M_WAITOK | M_ZERO);
164                         if (oia == NULL)
165                                 return (ENOBUFS);
166                         if ((ia = ipx_ifaddr) != NULL) {
167                                 for ( ; ia->ia_next != NULL; ia = ia->ia_next)
168                                         ;
169                                 ia->ia_next = oia;
170                         } else
171                                 ipx_ifaddr = oia;
172                         ia = oia;
173                         ifa = (struct ifaddr *)ia;
174                         IFA_LOCK_INIT(ifa);
175                         ifa->ifa_refcnt = 1;
176                         TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
177                         ia->ia_ifp = ifp;
178                         ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;
179 
180                         ifa->ifa_netmask = (struct sockaddr *)&ipx_netmask;
181 
182                         ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
183                         if (ifp->if_flags & IFF_BROADCAST) {
184                                 ia->ia_broadaddr.sipx_family = AF_IPX;
185                                 ia->ia_broadaddr.sipx_len = sizeof(ia->ia_addr);
186                                 ia->ia_broadaddr.sipx_addr.x_host = ipx_broadhost;
187                         }
188                 }
189                 break;
190         default:
191                 if (td && (error = priv_check(td, PRIV_NET_HWIOCTL)) != 0)
192                         return (error);
193         }
194 
195         switch (cmd) {
196 
197         case SIOCSIFDSTADDR:
198                 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
199                         return (EINVAL);
200                 if (ia->ia_flags & IFA_ROUTE) {
201                         rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
202                         ia->ia_flags &= ~IFA_ROUTE;
203                 }
204                 if (ifp->if_ioctl) {
205                         error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, (void *)ia);
206                         if (error)
207                                 return (error);
208                 }
209                 *(struct sockaddr *)&ia->ia_dstaddr = ifr->ifr_dstaddr;
210                 return (0);
211 
212         case SIOCSIFADDR:
213                 return (ipx_ifinit(ifp, ia,
214                                 (struct sockaddr_ipx *)&ifr->ifr_addr, 1));
215 
216         case SIOCDIFADDR:
217                 ipx_ifscrub(ifp, ia);
218                 ifa = (struct ifaddr *)ia;
219                 TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
220                 oia = ia;
221                 if (oia == (ia = ipx_ifaddr)) {
222                         ipx_ifaddr = ia->ia_next;
223                 } else {
224                         while (ia->ia_next && (ia->ia_next != oia)) {
225                                 ia = ia->ia_next;
226                         }
227                         if (ia->ia_next)
228                             ia->ia_next = oia->ia_next;
229                         else
230                                 printf("Didn't unlink ipxifadr from list\n");
231                 }
232                 IFAFREE((&oia->ia_ifa));
233                 return (0);
234 
235         case SIOCAIFADDR:
236                 dstIsNew = 0;
237                 hostIsNew = 1;
238                 if (ia->ia_addr.sipx_family == AF_IPX) {
239                         if (ifra->ifra_addr.sipx_len == 0) {
240                                 ifra->ifra_addr = ia->ia_addr;
241                                 hostIsNew = 0;
242                         } else if (ipx_neteq(ifra->ifra_addr.sipx_addr,
243                                          ia->ia_addr.sipx_addr))
244                                 hostIsNew = 0;
245                 }
246                 if ((ifp->if_flags & IFF_POINTOPOINT) &&
247                     (ifra->ifra_dstaddr.sipx_family == AF_IPX)) {
248                         if (hostIsNew == 0)
249                                 ipx_ifscrub(ifp, ia);
250                         ia->ia_dstaddr = ifra->ifra_dstaddr;
251                         dstIsNew  = 1;
252                 }
253                 if (ifra->ifra_addr.sipx_family == AF_IPX &&
254                                             (hostIsNew || dstIsNew))
255                         error = ipx_ifinit(ifp, ia, &ifra->ifra_addr, 0);
256                 return (error);
257 
258         default:
259                 if (ifp->if_ioctl == NULL)
260                         return (EOPNOTSUPP);
261                 return ((*ifp->if_ioctl)(ifp, cmd, data));
262         }
263 }
264 
265 /*
266 * Delete any previous route for an old address.
267 */
268 static void
269 ipx_ifscrub(struct ifnet *ifp, struct ipx_ifaddr *ia)
270 {
271 
272         if (ia->ia_flags & IFA_ROUTE) {
273                 if (ifp->if_flags & IFF_POINTOPOINT) {
274                         rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
275                 } else
276                         rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
277                 ia->ia_flags &= ~IFA_ROUTE;
278         }
279 }
280 /*
281  * Initialize an interface's internet address
282  * and routing table entry.
283  */
284 static int
285 ipx_ifinit(struct ifnet *ifp, struct ipx_ifaddr *ia,
286     struct sockaddr_ipx *sipx, int scrub)
287 {
288         struct sockaddr_ipx oldaddr;
289         int s = splimp(), error;
290 
291         /*
292          * Set up new addresses.
293          */
294         oldaddr = ia->ia_addr;
295         ia->ia_addr = *sipx;
296 
297         /*
298          * The convention we shall adopt for naming is that
299          * a supplied address of zero means that "we don't care".
300          * Use the MAC address of the interface. If it is an
301          * interface without a MAC address, like a serial line, the
302          * address must be supplied.
303          *
304          * Give the interface a chance to initialize
305          * if this is its first address,
306          * and to validate the address if necessary.
307          */
308         if (ifp->if_ioctl != NULL &&
309             (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (void *)ia))) {
310                 ia->ia_addr = oldaddr;
311                 splx(s);
312                 return (error);
313         }
314         splx(s);
315         ia->ia_ifa.ifa_metric = ifp->if_metric;
316         /*
317          * Add route for the network.
318          */
319         if (scrub) {
320                 ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
321                 ipx_ifscrub(ifp, ia);
322                 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
323         }
324         if (ifp->if_flags & IFF_POINTOPOINT)
325                 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
326         else {
327                 ia->ia_broadaddr.sipx_addr.x_net = ia->ia_addr.sipx_addr.x_net;
328                 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
329         }
330         ia->ia_flags |= IFA_ROUTE;
331         return (0);
332 }
333 
334 /*
335  * Return address info for specified internet network.
336  */
337 struct ipx_ifaddr *
338 ipx_iaonnetof(struct ipx_addr *dst)
339 {
340         struct ipx_ifaddr *ia;
341         struct ipx_addr *compare;
342         struct ifnet *ifp;
343         struct ipx_ifaddr *ia_maybe = NULL;
344         union ipx_net net = dst->x_net;
345 
346         for (ia = ipx_ifaddr; ia != NULL; ia = ia->ia_next) {
347                 if ((ifp = ia->ia_ifp) != NULL) {
348                         if (ifp->if_flags & IFF_POINTOPOINT) {
349                                 compare = &satoipx_addr(ia->ia_dstaddr);
350                                 if (ipx_hosteq(*dst, *compare))
351                                         return (ia);
352                                 if (ipx_neteqnn(net, ia->ia_addr.sipx_addr.x_net))
353                                         ia_maybe = ia;
354                         } else {
355                                 if (ipx_neteqnn(net, ia->ia_addr.sipx_addr.x_net))
356                                         return (ia);
357                         }
358                 }
359         }
360         return (ia_maybe);
361 }
362 
363 
364 void
365 ipx_printhost(struct ipx_addr *addr)
366 {
367         u_short port;
368         struct ipx_addr work = *addr;
369         char *p; u_char *q;
370         char *net = "", *host = "";
371         char cport[10], chost[15], cnet[15];
372 
373         port = ntohs(work.x_port);
374 
375         if (ipx_nullnet(work) && ipx_nullhost(work)) {
376 
377                 if (port)
378                         printf("*.%x", port);
379                 else
380                         printf("*.*");
381 
382                 return;
383         }
384 
385         if (ipx_wildnet(work))
386                 net = "any";
387         else if (ipx_nullnet(work))
388                 net = "*";
389         else {
390                 q = work.x_net.c_net;
391                 snprintf(cnet, sizeof(cnet), "%x%x%x%x",
392                         q[0], q[1], q[2], q[3]);
393                 for (p = cnet; *p == '' && p < cnet + 8; p++)
394                         continue;
395                 net = p;
396         }
397 
398         if (ipx_wildhost(work))
399                 host = "any";
400         else if (ipx_nullhost(work))
401                 host = "*";
402         else {
403                 q = work.x_host.c_host;
404                 snprintf(chost, sizeof(chost), "%x%x%x%x%x%x",
405                         q[0], q[1], q[2], q[3], q[4], q[5]);
406                 for (p = chost; *p == '' && p < chost + 12; p++)
407                         continue;
408                 host = p;
409         }
410 
411         if (port) {
412                 if (strcmp(host, "*") == 0) {
413                         host = "";
414                         snprintf(cport, sizeof(cport), "%x", port);
415                 } else
416                         snprintf(cport, sizeof(cport), ".%x", port);
417         } else
418                 *cport = 0;
419 
420         printf("%s.%s%s", net, host, cport);
421 }
422 

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.