chapter 17 routing sockets. abstract introduction datalink socket address structure reading and...
TRANSCRIPT
Chapter 17 routing sockets
abstract
• Introduction
• datalink socket address structure
• reading and writing
• sysctl operation
• get_ifi_info function
• interface name and index fuction
Introduction• Access the Unix routing table within the kernel
– ioctl command (SIOCADDRT, SIODELRT)
– netstat: read the kernel memory to obtain the contents of the routing table
• Routing daemons (gated)– monitor ICMP
– AF_ROUTE domain => cleaned up the interface to the kernel’s routing system
– only type of socket supported in the route domain => raw socket
• Three type of operation on routing socket– process can send a message to the kernel by wri
ting to a routing socket(addition and deletion of routes, Only superuser)
– process can read a message from the kernel on a routing socket (Only superuser)
– process can use the sysctl function to either dump the routing table or to list all the configured interface
datalink socket address structure• Returned by routing socket <net/if_dl.h>
Structure sockaddr_dl{uint8_t sdl_len;sa_family_t sdl_family; /*AF_LINK*/uint16_t sdl_index;/*system assigned index*/uint8_t sdl_type; /*IFT_ETHER*/uint8_t sdl_nlen; /*name length*/uint8_t sdl_alen;/*link-layer address length*/uint8_t sdl_slen;/* link-layer selector length */char sdl_data[12];/*minimum work area, name and link-layer address*/};
reading and writing
• After a process create a routing socket, it can send commands to the kernel by writing to the socket and read information from the kernel by reading from the socket
• Three different structure are exchanged across a routing socket– rt_msghdr, if_msghdr, ifa_msghdr (fi
gure 17-3)
Figure 17-2
rt_msghdr{}
rtm _ typ e =R TM _ G E T
destina tionsocke t
add ressstruc tu re
buff er sentto kernel
RTA_DST
rt_msghdr{}
rtm _ typ e =R TM _ G E T
destinationsocket
addressstructure
genmasksocket
addressstructure
netmasksocket
addressstructure
gatewaysocket
addressstructure
buff er returnedby kernel
RTA_DST
RTA_GATEWAY
RTA_NETMASK
RTA_GENMASK
Data exchanged with kernel across routing socket
for RTM_GET command
Figure 17-6#include "unproute.h"
#define BUFLEN (sizeof(struct rt_msghdr) + 512)
/* 8 * sizeof(struct sockaddr_in6) = 192 */
#define SEQ 9999
int main(int argc, char **argv)
{
int sockfd;
char *buf;
pid_t pid;
ssize_t n;
struct rt_msghdr *rtm;
struct sockaddr *sa, *rti_info[RTAX_MAX];
struct sockaddr_in *sin;
Figure 17-6(2)if (argc != 2) err_quit("usage: getrt <IPaddress>");
sockfd = Socket(AF_ROUTE, SOCK_RAW, 0); /* need superuser privileges */
buf = Calloc(1, BUFLEN); /* and initialized to 0 */
rtm = (struct rt_msghdr *) buf;
rtm->rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in);
rtm->rtm_version = RTM_VERSION;
rtm->rtm_type = RTM_GET;
rtm->rtm_addrs = RTA_DST;
rtm->rtm_pid = pid = getpid();
rtm->rtm_seq = SEQ;
sin = (struct sockaddr_in *) (rtm + 1);
sin->sin_family = AF_INET;
Inet_pton(AF_INET, argv[1], &sin->sin_addr);
Write(sockfd, rtm, rtm->rtm_msglen);
do {
n = Read(sockfd, rtm, BUFLEN);
} while (rtm->rtm_type != RTM_GET || rtm->rtm_seq != SEQ ||
rtm->rtm_pid != pid);
Figure 17-6(2)rtm = (struct rt_msghdr *) buf;
sa = (struct sockaddr *) (rtm + 1);
get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
if ( (sa = rti_info[RTAX_DST]) != NULL)
printf("dest: %s\n", Sock_ntop_host(sa, sa->sa_len));
if ( (sa = rti_info[RTAX_GATEWAY]) != NULL)
printf("gateway: %s\n", Sock_ntop_host(sa, sa->sa_len));
if ( (sa = rti_info[RTAX_NETMASK]) != NULL)
printf("netmask: %s\n", Sock_masktop(sa, sa->sa_len));
if ( (sa = rti_info[RTAX_GENMASK]) != NULL)
printf("genmask: %s\n", Sock_masktop(sa, sa->sa_len));
exit(0);
}
rt_msghdr{}
rtm _ type =R TM _G E T
destinationsocket
addressstructure
genmasksocket
addressstructure
netmasksocket
addressstructure
gatewaysocket
addressstructure
buff er returnedby kernel
RTA_DST
RTA_GATEWAY
RTA_NETMASK
RTA_GENMASK
rti_ info [ RTAX_DST]
rti_ info [ RTAX_GATEWAY]
rti_ info [ RTAX_NETMASK]
rti_ info [ RTAX_GENMASK]
rti_ info [ RTAX_IFP ]
rti_ info [ RTAX_IFA]
rti_ info [ RTAX_AUTHOR]
rti_ info [ RTAX_BRD]
NULL
NULLNULL
NULL
rti_info structure filled in by our get_rtaddrs function
Figure 17-9#include "unproute.h"
#define ROUNDUP(a, size) (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a))
/* Step to next socket address structure;
if sa_len is 0, assume it is sizeof(u_long).
*/
#define NEXT_SA(ap) ap = (struct sockaddr *) \
((caddr_t) ap + (ap->sa_len ? ROUNDUP(ap->sa_len, sizeof (u_long)) : \
sizeof(u_long)))
void get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
{
int i;
for (i = 0; i < RTAX_MAX; i++) {
if (addrs & (1 << i)) {
rti_info[i] = sa;
NEXT_SA(sa);
} else rti_info[i] = NULL;
}
}
sysctl operation
• Any process can examine both the routing table and the interface list.
#include <sys/param.h>#include <sys/sysctl.h>
int sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,void *newp, size_t newlen); returns:0 if OK, -1 on error
C TL_NETC TL_MAC HDEPC TL_KERNC TL_HWC TL_DEBUG C TL_VF SC TL_USER
AF _INET AF _LINE AF_ROUTE AF _UNSP EC
IP P RO TO _IC MP IP P RO TO _IG MP IP P RO TO _IP IP P RO TO _TC P IP P RO TO _UDP
Hierarchical arrangement of sysctl names
name[ ]
0
1
2
3
4
5
C TL_NET
AF_ROUTE
0
AF_INET
NET_RT_DUMP
0
C TL_NET
AF_ROUTE
0
AF_INET
NET_RT_FLAGS
RTF_LLINFO
C TL_NET
AF_ROUTE
0
AF_INET
NET_RT_IFLIST
0
return IP v4routing table
return IP v4arp cache
returninterface lis t
Sysctl information returned for route domain
if_msghdr{}
ifm_type =RTM_IFINFO
datalinksocket
addressstructure
unicast addrsocket
addressstructure
netmasksocket
addressstructure
ifa_msghdr{}ifam_type =
RTM_NEWADDR
buffer returnedby kernel
broadcast addrsocket
addressstructure
One per interface:
interface name, index, and hardware address
One per address:
configured for the interface
Information returned for sysctl,CTL_NET,NET_RT_IFLIST command
Figure 17-14#include "unproute.h"
#include <netinet/udp.h>
#include <netinet/ip_var.h>
#include <netinet/udp_var.h> /* for UDPCTL_xxx constants */
int main(int argc, char **argv)
{
int mib[5], val;
size_t len;
mib[0] = CTL_NET;
mib[1] = AF_INET;
mib[2] = IPPROTO_UDP;
mib[3] = UDPCTL_CHECKSUM;
len = sizeof(val);
Sysctl(mib, 4, &val, &len, NULL, 0);
printf("udp checksum flag: %d\n", val);
exit(0);
}
interface name and index fuction
• RFC 2133 defines four function that deal with interface names and indexes
==>these are used with IPv6 multicasting(chapter 19)
• each interface has a unique name and a unique positive index(0 is never used )
#include <net/if.h>unsigned int if_nametoindex(const char *ifname); returns:positive interface index if OK, 0 on error
char *if_indextoname(unsigned int ifindex, char *ifname); returns:pointer to interface name if OK, NULL on error
struct if_nameindex *if_nameindex(void); returns:nonnull pointer if OK, NULL on error
void if_freenameindex(struct if_nameindex *ptr);
• if_nameindex return a pointer to an array of if_nameindex structure
Struct if_nameindex{ unsigned int if_index;/*1, 2,…...*/ char *if_name;/*null terminated name*/}