#include #include #include #include #include #include #include #include #include #include #include int rtnl_open() { struct sockaddr_nl rtaddr; int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); int rtaddr_len; if(fd <0) { perror("rtnl_open"); return -1; } rtaddr.nl_family = AF_NETLINK; rtaddr.nl_groups = 0xFFFFFFFF; if(bind(fd,(struct sockaddr*)&rtaddr,sizeof(rtaddr))<0) { perror("rtnl_open"); return -1; } rtaddr_len = sizeof(rtaddr); getsockname(fd,(struct sockaddr*)&rtaddr,&rtaddr_len); return fd; } int rtnl_recvfrom(int fd) { struct nlmsghdr *h; struct sockaddr_nl nladdr; struct iovec iov; int tot_len; char buf[8192]; struct msghdr msg = { (void*)&nladdr, sizeof(nladdr), &iov, 1, NULL, 0, 0 }; memset(&nladdr, 0, sizeof(nladdr)); nladdr.nl_family = AF_NETLINK; nladdr.nl_pid = 0; nladdr.nl_groups = 0; iov.iov_base = buf; iov.iov_len = sizeof(buf); if((tot_len = recvmsg(fd,&msg,0)) == 0) { /* EOF */ } for (h = (struct nlmsghdr*)buf;tot_len >= sizeof(*h); ) { int len = h->nlmsg_len; if(!NLMSG_OK(h,tot_len)) { fprintf(stderr,"short message\n"); } else { switch(h->nlmsg_type) { case RTM_NEWROUTE: fprintf(stderr,"RTM_NEWROUTE\n"); goto process_rtm; case RTM_DELROUTE: fprintf(stderr,"RTM_DELROUTE\n"); process_rtm: { struct rtmsg *rtm = NLMSG_DATA(h); struct rtattr *tb[RTA_MAX+1]; struct rtattr *rta = RTM_RTA(rtm); int i; memset(tb,0,sizeof(tb)); while(RTA_OK(rta, len)) { if(rta->rta_type <= RTA_MAX) tb[rta->rta_type] = rta; rta = RTA_NEXT(rta,len); } for(i=0;inlmsg_type); break; } } h = NLMSG_NEXT(h,tot_len); } return 0; } int rtnl_send(int fd, unsigned char *buf, int len) { struct sockaddr_nl nladdr; int i; memset(&nladdr, 0, sizeof(nladdr)); nladdr.nl_family = AF_NETLINK; #if 0 for(i=0;irtnl_family = AF_INET; memcpy(data,mol_req,sizeof(struct mpls_out_label_req)); return rtnl_send(netlink,(unsigned char*)&req,sizeof(req)); } int send_ilm(int netlink,struct mpls_in_label_req *mil_req,int cmd) { struct { struct nlmsghdr n; struct mpls_in_label_req m; } req; void *data = NLMSG_DATA(&req); memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct mpls_in_label_req)); req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE; req.n.nlmsg_type = cmd; mil_req->rtnl_family = AF_INET; memcpy(data,mil_req,sizeof(struct mpls_in_label_req)); return rtnl_send(netlink,(unsigned char*)&req,sizeof(req)); } int send_ftn(int netlink,struct mpls_bind_fec_req *mbf_req,int cmd) { struct { struct nlmsghdr n; struct mpls_bind_fec_req m; } req; void *data = NLMSG_DATA(&req); memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct mpls_bind_fec_req)); req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE; req.n.nlmsg_type = cmd; mbf_req->rtnl_family = AF_INET; memcpy(data,mbf_req,sizeof(struct mpls_bind_fec_req)); return rtnl_send(netlink,(unsigned char*)&req,sizeof(req)); } int send_xc(int netlink,struct mpls_xconnect_req *mx_req,int cmd) { struct { struct nlmsghdr n; struct mpls_xconnect_req m; } req; void *data = NLMSG_DATA(&req); memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct mpls_xconnect_req)); req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE; req.n.nlmsg_type = cmd; mx_req->rtnl_family = AF_INET; memcpy(data,mx_req,sizeof(struct mpls_xconnect_req)); return rtnl_send(netlink,(unsigned char*)&req,sizeof(req)); } int send_instr(int netlink,struct mpls_instruction_req *mir_req,int cmd) { struct { struct nlmsghdr n; struct mpls_instruction_req m; } req; void *data = NLMSG_DATA(&req); memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct mpls_instruction_req)); req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE; req.n.nlmsg_type = cmd; mir_req->rtnl_family = AF_INET; memcpy(data,mir_req,sizeof(struct mpls_instruction_req)); return rtnl_send(netlink,(unsigned char*)&req,sizeof(req)); }