#include "rsvp_label.h" #include #include #ifdef LABEL char *labelconffile = "/etc/label.conf"; #endif int find_interface(char *interface_name) { int i; for(i = 0; i < MAX_INTERFACE_LIMIT; i++) { if(!strcmp(interface_name,Interface[i])){ return(i); } } printf("no labels set for interface %s \n",interface_name); return(-1); } u_int32_t Get_Label(int vif){ int i,j; i = find_interface(if_vec[vif].if_name); if(i == -1) return(0); for(j = 1;j <= LabelInitTable[i][0].Label;j++) { if(LabelInitTable[i][j].use_flag == 0) { LabelInitTable[i][j].use_flag = 1; return(LabelInitTable[i][j].Label); } } return(0); } int Free_Label(char *interface_name, u_int32_t Label){ int i,j; i = find_interface(interface_name); if(i == -1) return(0); for(j = 1;j <= LabelInitTable[i][0].Label;j++) { if(LabelInitTable[i][j].Label == Label){ LabelInitTable[i][j].use_flag = 0; printf("Lable on Interface freed %s %u \n",interface_name,Label); return(1); } } printf("Lable Interface mismatch %s %u \n",interface_name,Label); return(0); } int Init_Table(){ FILE *fp; int i,j; char str[80]; char interface[5]; u_int32_t labelstart; int total; int s; for(i = 0; i < MAX_INTERFACE_LIMIT; i++) strcpy(Interface[i],""); for(i = 0; i < MAX_INTERFACE_LIMIT; i++) for(j = 0; j < MAX_LABEL_LIMIT; j++) { LabelInitTable[i][j].Label = 0; LabelInitTable[i][j].use_flag = 0; } fp = fopen(labelconffile,"r"); if(!fp){ printf("could not access label init file no label switching \n"); return -1; } while(!feof(fp)){ fgets(str,80,fp); if(strncmp(str,"#",1)) { sscanf(str,"%s %d %u\n",interface,&total,&labelstart); for(i = 0 ; i < MAX_INTERFACE_LIMIT; i++) { if(!strcmp(Interface[i],"")) { strcpy(Interface[i], interface); break; } if(!strcmp(Interface[i],interface)) break; } LabelInitTable[i][0].Label = (u_int32_t)total; for(j = 1; j <= total ; j++) { LabelInitTable[i][j].Label = labelstart + j - 1; } close(s); } } fclose(fp); return 0; } int release_label_interface() { return 0; } Label * new_label_obj(u_char ctype) { int size; Label *labelp; size = sizeof(Label); labelp = (Label *)malloc(size); assert(labelp); Obj_Length(labelp) = size; Obj_Class(labelp) = class_Label; Obj_CType(labelp) = ctype; return(labelp); } int IsLabelEnabled(char *iname) { int s; s = find_interface(iname); if(s == -1) return(0); else return 1; } int pass_msg_2_rtsock (LabelTableEntryPtr ltentry, char *iface_name, int type) { int s,i; char buf[2048]; struct rt_msghdr *rtm; bzero(buf,2048); rtm = (struct rt_msghdr *)buf; memcpy((buf + sizeof(struct rt_msghdr)), (char *)ltentry, sizeof(LabelTableEntry)); if(iface_name) { memcpy((buf + sizeof(struct rt_msghdr) + sizeof(LabelTableEntry)), (char *)iface_name, strlen(iface_name)); rtm->rtm_msglen = sizeof(struct rt_msghdr) + sizeof(LabelTableEntry) + strlen(iface_name); } else { buf[sizeof(struct rt_msghdr) + sizeof(LabelTableEntry)] = '\0'; rtm->rtm_msglen = sizeof(struct rt_msghdr) + sizeof(LabelTableEntry) + 1; } s = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC); if(s < 0 ) { perror("socket"); return -1; } rtm->rtm_version = RTM_VERSION; rtm->rtm_type = type; i = write(s, buf, (size_t)rtm->rtm_msglen); if(i < 0) { perror("Write error !!"); return -1; } close(s); return 0; } int Add_label_to_route( Session *dest, RSB* rp) { int length; Label *label; LabelTableEntryPtr ltentry; label = rp->rs_label; length = Obj_Length(label); ltentry = (LabelTableEntryPtr)malloc(sizeof(LabelTableEntry)); #ifdef EDGE /* processing for Egress and Ingress devices */ switch (rp->action_flag) { case LTE_PUSH: ltentry->lteNewLabel = label->label_obj; ltentry->lteLabel = label->label_obj; ltentry->lteFlags = LTE_PUSH; SetEthLabel(label_add.cbq_newlabel, label->label_obj); break; case LTE_POP: ltentry->lteNewLabel = label->label_obj; ltentry->lteLabel = label->label_obj; ltentry->lteFlags = LTE_POP; SetEthLabel(label_add.cbq_newlabel, label->label_obj); break; case LTE_SWAP: ltentry->lteNewLabel = rp->rs_labelout; ltentry->lteLabel = label->label_obj; ltentry->lteFlags = LTE_SWAP; SetEthLabel(label_add.cbq_newlabel, rp->rs_labelout); break; } #else if(dest->d_PSB_list->ps_rsvp_phop.hop4_addr.s_addr == 0) { ltentry->lteNewLabel = label->label_obj; ltentry->lteLabel = label->label_obj; ltentry->lteFlags = LTE_PUSH; } else { ltentry->lteNewLabel = rp->rs_labelout; ltentry->lteLabel = label->label_obj; #ifdef CAIRN ltentry->lteFlags = rp->action_flag; #else ltentry->lteFlags = LTE_SWAP; #endif } #endif if(dest->d_session->sess_header.obj_ctype == ctype_SESSION_lsp_tunv4) { ltentry->lteDest = dest->d_session->sesslsp_addr.s_addr; ltentry->lteDestLtpPort = 0; ltentry->lteDestLtpProtocol = 0; ltentry->lteSourceLtpPort = 0; ltentry->lteSourceLtpProtocol = 0; ltentry->lteSource = 0; }else { ltentry->lteDest = dest->d_session->sess4_addr.s_addr; ltentry->lteDestLtpPort = dest->d_session->sess4_port; ltentry->lteDestLtpProtocol = dest->d_session->sess4_prot; ltentry->lteSourceLtpPort = rp->rs_filtstar->fst_p->fst_filtp->filt4_srcport; ltentry->lteSourceLtpProtocol = dest->d_session->sess4_prot; ltentry->lteSource = rp->rs_filtstar->fst_p->fst_filtp->filt4_srcaddr.s_addr; } ltentry->lteDestLtpPad = 0; ltentry->lteSourceLtpPad = 0; ltentry->lteNextHopAddr = rp->label_nhop; ltentry->lteCoS = 0; /* Not supported so far */ ltentry->lteStatsOut = 0; if( pass_msg_2_rtsock(ltentry,if_vec[rp->rs_OIf].if_name,LABEL_ADD) < 0) return (-1); else return(0); } #ifdef TUNNEL u_int32_t get_nhop(nhop) struct sockaddr_in nhop; { int s,i; struct rt_msghdr *msghdr; char buf[124]; char str[192]; struct sockaddr* dst; struct sockaddr_dl* result; struct rt_addrinfo info; u_int32_t sam; int found = 0; do{ s = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC); if(s < 0 ) perror("socket"); msghdr = (struct rt_msghdr*)buf; msghdr->rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr); msghdr->rtm_pid = (int)getpid(); msghdr->rtm_version = 5; msghdr->rtm_type = RTM_GET; dst = (struct sockaddr*)(buf + sizeof(struct rt_msghdr)); bcopy(&nhop, dst, sizeof(nhop)); msghdr->rtm_addrs |= RTA_DST; i = write(s, (caddr_t)msghdr, (size_t)msghdr->rtm_msglen); if (i < 0) perror("Write error !!"); i = read(s, (caddr_t)str, (size_t)(192)); if (i < 0) perror(" Read Error !!"); close(s); msghdr = (struct rt_msghdr*)str; info.rti_addrs = msghdr->rtm_addrs; rt_xaddrs((caddr_t)(msghdr + 1), 192 + (caddr_t)msghdr, &info); if( info.rti_addrs & RTAX_GATEWAY) { result = (struct sockaddr_dl*)info.rti_info[1]; if( result->sdl_family == AF_LINK) { bcopy(LLADDR(result), &sam, sizeof(sam)); found = 1; } else { bcopy((struct sockaddr_in*)info.rti_info[1], &nhop, sizeof(nhop)); found = 0; } } } while(!found); return(nhop.sin_addr.s_addr); } #endif #ifdef CAIRN u_int32_t get_pseudohdr(nhop) struct sockaddr_in nhop; { int s,i; struct rt_msghdr *msghdr; char buf[124]; char str[192]; struct sockaddr* dst; struct sockaddr_dl* result; struct rt_addrinfo info; u_int32_t sam; int found = 0; do{ s = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC); if(s < 0 ) perror("socket"); msghdr = (struct rt_msghdr*)buf; msghdr->rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr); msghdr->rtm_pid = (int)getpid(); msghdr->rtm_version = 5; msghdr->rtm_type = RTM_GET; dst = (struct sockaddr*)(buf + sizeof(struct rt_msghdr)); bcopy(&nhop, dst, sizeof(nhop)); msghdr->rtm_addrs |= RTA_DST; i = write(s, (caddr_t)msghdr, (size_t)msghdr->rtm_msglen); if (i < 0) perror("Write error !!"); i = read(s, (caddr_t)str, (size_t)(192)); if (i < 0) perror(" Read Error !!"); close(s); msghdr = (struct rt_msghdr*)str; info.rti_addrs = msghdr->rtm_addrs; rt_xaddrs((caddr_t)(msghdr + 1), 192 + (caddr_t)msghdr, &info); if( info.rti_addrs & RTAX_GATEWAY) { result = (struct sockaddr_dl*)info.rti_info[1]; if( result->sdl_family == AF_LINK) { bcopy(LLADDR(result), &sam, sizeof(sam)); found = 1; } else { bcopy((struct sockaddr_in*)info.rti_info[1], &nhop, sizeof(nhop)); found = 0; } } } while(!found); return(sam); } #endif #if defined(CAIRN) || defined(TUNNEL) int rt_xaddrs(cp, cplim, rtinfo) register caddr_t cp, cplim; register struct rt_addrinfo *rtinfo; { register struct sockaddr *sa; register int i; bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info)); for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { if ((rtinfo->rti_addrs & (1 << i)) == 0) continue; sa = (struct sockaddr *)cp; /* * It won't fit. */ if ( (cp + sa->sa_len) > cplim ) { return (-1); } /* * there are no more.. quit now * If there are more bits, they are in error. * I've seen this. route(1) can evidently generate these. * This causes kernel to core dump. * for compatibility, If we see this, point to a safe address. */ if (sa->sa_len == 0) { rtinfo->rti_info[i] = &sa_zero; return (0); /* should be EINVAL but for compat */ } /* accept it */ rtinfo->rti_info[i] = sa; ADVANCE(cp, sa); } return (0); } #endif