2 * Copyright (c) 1999, Boris Popov
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Boris Popov.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * $FreeBSD: src/lib/libncp/ipx.c,v 1.1 1999/10/12 11:56:37 bp Exp $
33 * $DragonFly: src/lib/libncp/ipx.c,v 1.4 2008/09/30 16:57:05 swildner Exp $
35 #include <sys/param.h>
36 #include <sys/ioctl.h>
37 #include <sys/socket.h>
38 #include <sys/sysctl.h>
42 #include <net/if_var.h>
43 #include <net/if_dl.h>
44 #include <net/if_types.h>
45 #include <net/route.h>
48 #include <netipx/ipx.h>
49 #include <netipx/ipx_if.h>
60 #include <netncp/ncp_lib.h>
62 #define IPX_NODE_LEN 6
64 typedef u_long IPXNet
;
65 typedef u_short IPXPort
;
66 typedef union ipx_host IPXNode
;
70 ipx_fprint_node(FILE * file
, IPXNode node
){
71 fprintf(file
, "%02X%02X%02X%02X%02X%02X",
72 (unsigned char) node
.c_host
[0],
73 (unsigned char) node
.c_host
[1],
74 (unsigned char) node
.c_host
[2],
75 (unsigned char) node
.c_host
[3],
76 (unsigned char) node
.c_host
[4],
77 (unsigned char) node
.c_host
[5]
82 ipx_fprint_network(FILE * file
, const IPXNet net
){
83 fprintf(file
, "%08X", (u_int32_t
)ntohl(net
));
87 ipx_fprint_port(FILE * file
, IPXPort port
)
89 fprintf(file
, "%04X", ntohs(port
));
93 ipx_fprint_addr(FILE * file
, struct ipx_addr
*ipx
)
95 ipx_fprint_network(file
, ipx_netlong(*ipx
));
97 ipx_fprint_node(file
, ipx
->x_host
);
99 ipx_fprint_port(file
, ipx
->x_port
);
103 ipx_print_node(IPXNode node
)
105 ipx_fprint_node(stdout
, node
);
109 ipx_print_network(IPXNet net
)
111 ipx_fprint_network(stdout
, net
);
115 ipx_print_port(IPXPort port
)
117 ipx_fprint_port(stdout
, port
);
121 ipx_print_addr(struct ipx_addr
*ipx
)
123 ipx_fprint_addr(stdout
, ipx
);
127 ipx_sscanf_node(char *buf
, unsigned char node
[6])
132 if ((i
= sscanf(buf
, "%2x%2x%2x%2x%2x%2x",
133 &(n
[0]), &(n
[1]), &(n
[2]),
134 &(n
[3]), &(n
[4]), &(n
[5]))) != 6)
138 for (i
= 0; i
< 6; i
++)
146 ipx_sscanf_saddr(char *buf
, struct sockaddr_ipx
*target
)
149 struct sockaddr_ipx addr
;
150 unsigned long sipx_net
;
152 addr
.sipx_family
= AF_IPX
;
153 /*!! addr.sipx_type = NCP_PTYPE;*/
155 if (sscanf(buf
, "%lx", &sipx_net
) != 1)
159 ((union ipx_net_u
*)(&addr
.sipx_addr
.x_net
))->long_e
= htonl(sipx_net
);
160 if ((p
= strchr(buf
, ':')) == NULL
){
164 if (ipx_sscanf_node(p
, addr
.sipx_node
) != 6)
168 if ((p
= strchr(p
, ':')) == NULL
)
173 if (sscanf(p
, "%hx", &addr
.sipx_port
) != 1)
177 addr
.sipx_port
= htons(addr
.sipx_port
);
183 void ipx_assign_node(IPXNode
*dest
, IPXNode
*src
) {
184 memcpy(dest
, src
, IPX_NODE_LEN
);
188 static void rt_xaddrs (caddr_t
, caddr_t
, struct rt_addrinfo
*);
189 static int if_ipxscan (int addrcount
, struct sockaddr_dl
*sdl
, struct if_msghdr
*ifm
,
190 struct ifa_msghdr
*ifam
,struct ipx_addr
*addr
);
193 * Find an IPX interface.
194 * ifname specifies interface name, if NULL search for all interfaces
195 * if ifname[0]='0', also all interfaces, but return its name
196 * addr on input preferred net address can be specified or 0 for any,
197 * on return contains full address (except port)
198 * returns 0 if interface was found
201 ipx_iffind(char *ifname
,struct ipx_addr
*addr
){
203 int all
=0, flags
, foundit
= 0, addrcount
;
204 struct if_msghdr
*ifm
, *nextifm
;
205 struct ifa_msghdr
*ifam
;
206 struct sockaddr_dl
*sdl
;
207 char *buf
, *lim
, *next
;
212 strncpy(name
,ifname
,sizeof(name
)-1);
222 mib
[4] = NET_RT_IFLIST
;
225 if (sysctl(mib
, 6, NULL
, &needed
, NULL
, 0) < 0)
227 if ((buf
= malloc(needed
)) == NULL
)
229 if (sysctl(mib
, 6, buf
, &needed
, NULL
, 0) < 0) {
237 ifm
= (struct if_msghdr
*)next
;
238 if (ifm
->ifm_type
== RTM_IFINFO
) {
239 sdl
= (struct sockaddr_dl
*)(ifm
+ 1);
240 flags
= ifm
->ifm_flags
;
242 fprintf(stderr
, "if_ipxfind: out of sync parsing NET_RT_IFLIST\n");
243 fprintf(stderr
, "expected %d, got %d\n", RTM_IFINFO
, ifm
->ifm_type
);
244 fprintf(stderr
, "msglen = %d\n", ifm
->ifm_msglen
);
245 fprintf(stderr
, "buf:%p, next:%p, lim:%p\n", buf
, next
, lim
);
250 next
+= ifm
->ifm_msglen
;
254 nextifm
= (struct if_msghdr
*)next
;
255 if (nextifm
->ifm_type
!= RTM_NEWADDR
)
258 ifam
= (struct ifa_msghdr
*)nextifm
;
260 next
+= nextifm
->ifm_msglen
;
264 if ((flags
& IFF_UP
) == 0)
265 continue; /* not up */
266 strncpy(name
, sdl
->sdl_data
, sdl
->sdl_nlen
);
267 name
[sdl
->sdl_nlen
] = '\0';
269 if (strlen(name
) != sdl
->sdl_nlen
)
270 continue; /* not same len */
271 if (strncmp(name
, sdl
->sdl_data
, sdl
->sdl_nlen
) != 0)
272 continue; /* not same name */
275 foundit
=if_ipxscan(addrcount
, sdl
, ifm
, ifam
, addr
);
277 if( ifname
!=NULL
&& ifname
[0]==0) {
278 strncpy(ifname
,sdl
->sdl_data
, sdl
->sdl_nlen
);
279 ifname
[sdl
->sdl_nlen
]=0;
286 return foundit
? 0:1;
291 if_ipxscan(int addrcount
, struct sockaddr_dl
*sdl
, struct if_msghdr
*ifm
,
292 struct ifa_msghdr
*ifam
, struct ipx_addr
*addr
)
294 struct rt_addrinfo info
;
295 struct sockaddr_ipx
*sipx
;
298 if ((s
= socket(AF_IPX
, SOCK_DGRAM
, 0)) < 0) {
299 perror("ifconfig: socket");
303 while (addrcount
> 0) {
304 info
.rti_addrs
= ifam
->ifam_addrs
;
305 /* Expand the compacted addresses */
306 rt_xaddrs((char *)(ifam
+ 1), ifam
->ifam_msglen
+ (char *)ifam
, &info
);
308 ifam
= (struct ifa_msghdr
*)((char *)ifam
+ ifam
->ifam_msglen
);
309 if (info
.rti_info
[RTAX_IFA
]->sa_family
== AF_IPX
) {
310 sipx
= (struct sockaddr_ipx
*)info
.rti_info
[RTAX_IFA
];
311 if( ipx_nullnet(sipx
->sipx_addr
) ) continue;
312 if( ipx_nullnet(*addr
) ||
313 ipx_neteq(sipx
->sipx_addr
,*addr
) ) {
314 *addr
=sipx
->sipx_addr
;
324 * Expand the compacted form of addresses as returned via the
325 * configuration read via sysctl().
329 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
330 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
333 rt_xaddrs(caddr_t cp
, caddr_t cplim
, struct rt_addrinfo
*rtinfo
)
338 memset(rtinfo
->rti_info
, 0, sizeof(rtinfo
->rti_info
));
339 for (i
= 0; (i
< RTAX_MAX
) && (cp
< cplim
); i
++) {
340 if ((rtinfo
->rti_addrs
& (1 << i
)) == 0)
342 rtinfo
->rti_info
[i
] = sa
= (struct sockaddr
*)cp
;