diff options
Diffstat (limited to 'sysdeps/unix/sysv')
-rw-r--r-- | sysdeps/unix/sysv/linux/if_index.c | 12 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/ifaddrs.c | 168 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/netinet/if_tr.h | 78 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/netlinkaccess.h | 5 |
4 files changed, 202 insertions, 61 deletions
diff --git a/sysdeps/unix/sysv/linux/if_index.c b/sysdeps/unix/sysv/linux/if_index.c index 377ccf5199..66f0ac1317 100644 --- a/sysdeps/unix/sysv/linux/if_index.c +++ b/sysdeps/unix/sysv/linux/if_index.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1997,98,99,2000,2002,2003,2004 Free Software Foundation, Inc. +/* Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -188,12 +189,8 @@ if_nameindex_netlink (void) /* Tell the kernel that we wish to get a list of all - active interfaces. */ - if (__netlink_sendreq (&nh, RTM_GETLINK) < 0) - goto exit_close; - - /* Collect all data for every interface. */ - if (__netlink_receive (&nh) < 0) + active interfaces. Collect all data for every interface. */ + if (__netlink_request (&nh, RTM_GETLINK) < 0) goto exit_free; /* Count the interfaces. */ @@ -290,7 +287,6 @@ if_nameindex_netlink (void) exit_free: __netlink_free_handle (&nh); - exit_close: __netlink_close (&nh); return idx; diff --git a/sysdeps/unix/sysv/linux/ifaddrs.c b/sysdeps/unix/sysv/linux/ifaddrs.c index 8a052e212d..f743f702f0 100644 --- a/sysdeps/unix/sysv/linux/ifaddrs.c +++ b/sysdeps/unix/sysv/linux/ifaddrs.c @@ -1,5 +1,5 @@ /* getifaddrs -- get names and addresses of all network interfaces - Copyright (C) 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -17,6 +17,7 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include <alloca.h> #include <assert.h> #include <errno.h> #include <ifaddrs.h> @@ -24,6 +25,7 @@ #include <netinet/in.h> #include <netpacket/packet.h> #include <stdbool.h> +#include <stdint.h> #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> @@ -84,7 +86,7 @@ __netlink_free_handle (struct netlink_handle *h) } -int +static int __netlink_sendreq (struct netlink_handle *h, int type) { struct @@ -114,15 +116,39 @@ __netlink_sendreq (struct netlink_handle *h, int type) int -__netlink_receive (struct netlink_handle *h) +__netlink_request (struct netlink_handle *h, int type) { struct netlink_res *nlm_next; - char buf[4096]; - struct iovec iov = { buf, sizeof (buf) }; + struct netlink_res **new_nlm_list; + static volatile size_t buf_size = 4096; + char *buf; struct sockaddr_nl nladdr; struct nlmsghdr *nlmh; - int read_len; + ssize_t read_len; bool done = false; + bool use_malloc = false; + + if (__netlink_sendreq (h, type) < 0) + return -1; + + size_t this_buf_size = buf_size; + if (__libc_use_alloca (this_buf_size)) + buf = alloca (this_buf_size); + else + { + buf = malloc (this_buf_size); + if (buf != NULL) + use_malloc = true; + else + goto out_fail; + } + + struct iovec iov = { buf, this_buf_size }; + + if (h->nlm_list != NULL) + new_nlm_list = &h->end_ptr->next; + else + new_nlm_list = &h->nlm_list; while (! done) { @@ -136,33 +162,66 @@ __netlink_receive (struct netlink_handle *h) read_len = TEMP_FAILURE_RETRY (__recvmsg (h->fd, &msg, 0)); if (read_len < 0) - return -1; + goto out_fail; - if (msg.msg_flags & MSG_TRUNC) - return -1; + if (nladdr.nl_pid != 0) + continue; - nlm_next = (struct netlink_res *) malloc (sizeof (struct netlink_res) - + read_len); - if (nlm_next == NULL) - return -1; - nlm_next->next = NULL; - nlm_next->nlh = memcpy (nlm_next + 1, buf, read_len); - nlm_next->size = read_len; - nlm_next->seq = h->seq; - if (h->nlm_list == NULL) - h->nlm_list = nlm_next; - else - h->end_ptr->next = nlm_next; - h->end_ptr = nlm_next; + if (__builtin_expect (msg.msg_flags & MSG_TRUNC, 0)) + { + if (this_buf_size >= SIZE_MAX / 2) + goto out_fail; + + nlm_next = *new_nlm_list; + while (nlm_next != NULL) + { + struct netlink_res *tmpptr; + + tmpptr = nlm_next->next; + free (nlm_next); + nlm_next = tmpptr; + } + *new_nlm_list = NULL; + + if (__libc_use_alloca (2 * this_buf_size)) + buf = extend_alloca (buf, this_buf_size, 2 * this_buf_size); + else + { + this_buf_size *= 2; + + char *new_buf = realloc (use_malloc ? buf : NULL, this_buf_size); + if (new_buf == NULL) + goto out_fail; + new_buf = buf; + use_malloc = true; + } + buf_size = this_buf_size; + + iov.iov_base = buf; + iov.iov_len = this_buf_size; + + /* Increase sequence number, so that we can distinguish + between old and new request messages. */ + h->seq++; + + if (__netlink_sendreq (h, type) < 0) + goto out_fail; + + continue; + } + + size_t count = 0; + size_t remaining_len = read_len; for (nlmh = (struct nlmsghdr *) buf; - NLMSG_OK (nlmh, (size_t) read_len); - nlmh = (struct nlmsghdr *) NLMSG_NEXT (nlmh, read_len)) + NLMSG_OK (nlmh, remaining_len); + nlmh = (struct nlmsghdr *) NLMSG_NEXT (nlmh, remaining_len)) { - if (nladdr.nl_pid != 0 || (pid_t) nlmh->nlmsg_pid != h->pid + if ((pid_t) nlmh->nlmsg_pid != h->pid || nlmh->nlmsg_seq != h->seq) continue; + ++count; if (nlmh->nlmsg_type == NLMSG_DONE) { /* We found the end, leave the loop. */ @@ -176,11 +235,38 @@ __netlink_receive (struct netlink_handle *h) errno = EIO; else errno = -nlerr->error; - return -1; + goto out_fail; } } + + /* If there was nothing with the expected nlmsg_pid and nlmsg_seq, + there is no point to record it. */ + if (count == 0) + continue; + + nlm_next = (struct netlink_res *) malloc (sizeof (struct netlink_res) + + read_len); + if (nlm_next == NULL) + goto out_fail; + nlm_next->next = NULL; + nlm_next->nlh = memcpy (nlm_next + 1, buf, read_len); + nlm_next->size = read_len; + nlm_next->seq = h->seq; + if (h->nlm_list == NULL) + h->nlm_list = nlm_next; + else + h->end_ptr->next = nlm_next; + h->end_ptr = nlm_next; } + + if (use_malloc) + free (buf); return 0; + +out_fail: + if (use_malloc) + free (buf); + return -1; } @@ -268,7 +354,7 @@ getifaddrs (struct ifaddrs **ifap) unsigned int i, newlink, newaddr, newaddr_idx; int *map_newlink_data; size_t ifa_data_size = 0; /* Size to allocate for all ifa_data. */ - char *ifa_data_ptr; /* Pointer to the unused part of memory for + char *ifa_data_ptr; /* Pointer to the unused part of memory for ifa_data. */ int result = 0; @@ -288,28 +374,20 @@ getifaddrs (struct ifaddrs **ifap) #endif /* Tell the kernel that we wish to get a list of all - active interfaces. */ - if (__netlink_sendreq (&nh, RTM_GETLINK) < 0) - { - result = -1; - goto exit_close; - } - /* Collect all data for every interface. */ - if (__netlink_receive (&nh) < 0) + active interfaces, collect all data for every interface. */ + if (__netlink_request (&nh, RTM_GETLINK) < 0) { result = -1; goto exit_free; } - /* Now ask the kernel for all addresses which are assigned - to an interface. Since we store the addresses after the - interfaces in the list, we will later always find the - interface before the corresponding addresses. */ + to an interface and collect all data for every interface. + Since we store the addresses after the interfaces in the + list, we will later always find the interface before the + corresponding addresses. */ ++nh.seq; - if (__netlink_sendreq (&nh, RTM_GETADDR) < 0 - /* Collect all data for every interface. */ - || __netlink_receive (&nh) < 0) + if (__netlink_request (&nh, RTM_GETADDR) < 0) { result = -1; goto exit_free; @@ -327,7 +405,7 @@ getifaddrs (struct ifaddrs **ifap) continue; /* Walk through all entries we got from the kernel and look, which - message type they contain. */ + message type they contain. */ for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size)) { /* Check if the message is what we want. */ @@ -423,7 +501,7 @@ getifaddrs (struct ifaddrs **ifap) /* Interfaces are stored in the first "newlink" entries of our list, starting in the order as we got from the kernel. */ - ifa_index = map_newlink (ifim->ifi_index - 1, ifas, + ifa_index = map_newlink (ifim->ifi_index - 1, ifas, map_newlink_data, newlink); ifas[ifa_index].ifa.ifa_flags = ifim->ifi_flags; @@ -767,8 +845,6 @@ getifaddrs (struct ifaddrs **ifap) exit_free: __netlink_free_handle (&nh); - - exit_close: __netlink_close (&nh); return result; diff --git a/sysdeps/unix/sysv/linux/netinet/if_tr.h b/sysdeps/unix/sysv/linux/netinet/if_tr.h index 1a7bc68c98..45c39115f3 100644 --- a/sysdeps/unix/sysv/linux/netinet/if_tr.h +++ b/sysdeps/unix/sysv/linux/netinet/if_tr.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1997 Free Software Foundation, Inc. +/* Copyright (C) 1997, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -21,13 +21,83 @@ #include <sys/cdefs.h> #include <sys/types.h> -#include <asm/types.h> -#include <linux/if_tr.h> +/* IEEE 802.5 Token-Ring magic constants. The frame sizes omit the preamble + and FCS/CRC (frame check sequence). */ +#define TR_ALEN 6 /* Octets in one token-ring addr */ +#define TR_HLEN (sizeof (struct trh_hdr) + sizeof (struct trllc)) +#define AC 0x10 +#define LLC_FRAME 0x40 + +/* LLC and SNAP constants */ +#define EXTENDED_SAP 0xAA +#define UI_CMD 0x03 + +/* This is an Token-Ring frame header. */ +struct trh_hdr +{ + u_int8_t ac; /* access control field */ + u_int8_t fc; /* frame control field */ + u_int8_t daddr[TR_ALEN]; /* destination address */ + u_int8_t saddr[TR_ALEN]; /* source address */ + u_int16_t rcf; /* route control field */ + u_int16_t rseg[8]; /* routing registers */ +}; + +/* This is an Token-Ring LLC structure */ +struct trllc +{ + u_int8_t dsap; /* destination SAP */ + u_int8_t ssap; /* source SAP */ + u_int8_t llc; /* LLC control field */ + u_int8_t protid[3]; /* protocol id */ + u_int16_t ethertype; /* ether type field */ +}; + +/* Token-Ring statistics collection data. */ +struct tr_statistics +{ + unsigned long rx_packets; /* total packets received */ + unsigned long tx_packets; /* total packets transmitted */ + unsigned long rx_bytes; /* total bytes received */ + unsigned long tx_bytes; /* total bytes transmitted */ + unsigned long rx_errors; /* bad packets received */ + unsigned long tx_errors; /* packet transmit problems */ + unsigned long rx_dropped; /* no space in linux buffers */ + unsigned long tx_dropped; /* no space available in linux */ + unsigned long multicast; /* multicast packets received */ + unsigned long transmit_collision; + + /* detailed Token-Ring errors. See IBM Token-Ring Network + Architecture for more info */ + + unsigned long line_errors; + unsigned long internal_errors; + unsigned long burst_errors; + unsigned long A_C_errors; + unsigned long abort_delimiters; + unsigned long lost_frames; + unsigned long recv_congest_count; + unsigned long frame_copied_errors; + unsigned long frequency_errors; + unsigned long token_errors; + unsigned long dummy1; +}; + +/* source routing stuff */ +#define TR_RII 0x80 +#define TR_RCF_DIR_BIT 0x80 +#define TR_RCF_LEN_MASK 0x1f00 +#define TR_RCF_BROADCAST 0x8000 /* all-routes broadcast */ +#define TR_RCF_LIMITED_BROADCAST 0xC000 /* single-route broadcast */ +#define TR_RCF_FRAME2K 0x20 +#define TR_RCF_BROADCAST_MASK 0xC000 +#define TR_MAXRIFLEN 18 #ifdef __USE_BSD -struct trn_hdr { +struct trn_hdr +{ u_int8_t trn_ac; /* access control field */ u_int8_t trn_fc; /* field control field */ u_int8_t trn_dhost[TR_ALEN]; /* destination host */ diff --git a/sysdeps/unix/sysv/linux/netlinkaccess.h b/sysdeps/unix/sysv/linux/netlinkaccess.h index 6672e714ff..6b2d858c9d 100644 --- a/sysdeps/unix/sysv/linux/netlinkaccess.h +++ b/sysdeps/unix/sysv/linux/netlinkaccess.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2004 Free Software Foundation, Inc. +/* Copyright (C) 2004, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -55,8 +55,7 @@ extern int __no_netlink_support attribute_hidden; extern int __netlink_open (struct netlink_handle *h); extern void __netlink_close (struct netlink_handle *h); extern void __netlink_free_handle (struct netlink_handle *h); -extern int __netlink_sendreq (struct netlink_handle *h, int type); -extern int __netlink_receive (struct netlink_handle *h); +extern int __netlink_request (struct netlink_handle *h, int type); #endif /* netlinkaccess.h */ |