static int route_call(layer4_t *l4) { layer4_t *newl4; fprintf(stderr, "%s: msn ", __FUNCTION__); display_NR_IE(l4->msn); fprintf(stderr, "%s: nr ", __FUNCTION__); display_NR_IE(l4->nr); if (l4->usednr->typ == NR_TYPE_INTERN) { newl4 = get_free_channel(&kern_if, -1, NULL); if (!newl4) { l4->cause_loc = CAUSE_LOC_PNET_LOCUSER; l4->cause_val = CAUSE_USER_BUSY; l4->progress = PROGRESS_TONE; if_link(l4->nst, man_down, MAN_CLEAR_CALL | REQUEST, l4->channel, 0, NULL, 0); return(0); } l4->sdata = newl4; l4->rdata = newl4; newl4->sdata = l4; newl4->rdata = l4; l4->sbuf = &newl4->rbuf; newl4->sbuf = &l4->rbuf; newl4->msn[0] = l4->usednr->len +1; newl4->msn[1] = 0x81; memcpy(&newl4->msn[2], l4->usednr->nr, l4->usednr->len); if (l4->msn[0]) memcpy(newl4->nr, l4->msn, l4->msn[0] + 1); newl4->l1_prot = ISDN_PID_L1_B_64TRANS; if_link(newl4->nst, man_down, MAN_SETUP | REQUEST, newl4->channel, 0, NULL, 0); } else if (l4->usednr->typ == NR_TYPE_AUDIO) { l4->sdata = NULL; l4->rdata = NULL; strcpy(l4->display,"connect to AUDIO"); do_connect(l4); l4->display[0] = 0; deactivate_bchannel(l4); setup_bchannel_rawdev(l4); activate_bchannel(l4); } else if (l4->usednr->typ == NR_TYPE_VOIP) { l4->sdata = NULL; l4->rdata = NULL; sprintf(l4->display,"calling %s", l4->usednr->name); do_alert(l4); sprintf(l4->display,"connect to %s", l4->usednr->name); do_connect(l4); l4->display[0] = 0; deactivate_bchannel(l4); setup_bchannel_rawdev(l4); activate_bchannel(l4); } return(0); }
static int clear_call(layer4_t *l4) { if (l4->sdata) { layer4_t *peer = l4->sdata; if (l4->cause_val) { peer->cause_loc = l4->cause_loc; peer->cause_val = l4->cause_val; } else { peer->cause_loc = CAUSE_LOC_PNET_LOCUSER; peer->cause_val = CAUSE_NORMALUNSPECIFIED; } peer->progress = PROGRESS_TONE; peer->sbuf = NULL; peer->sdata = NULL; peer->rdata = NULL; if (peer->nst) if_link(peer->nst, man_down, MAN_CLEAR_CALL | REQUEST, peer->channel, 0, NULL, 0); } l4->sdata = NULL; l4->rdata = NULL; l4->sbuf = NULL; return(0); }
static int do_alert(layer4_t *l4) { if_link(l4->nst, man_down, MAN_ALERT | REQUEST, l4->channel, 0, NULL, 0); return(0); }
static int do_connect(layer4_t *l4) { if_link(l4->nst, man_down, MAN_CONNECT | REQUEST, l4->channel, 0, NULL, 0); return(0); }
static int l3down(layer3_t *l3, u_int prim, int dinfo, struct sk_buff *skb) { int err = -EINVAL; if (!skb) err = if_link(&l3->inst.down, prim, dinfo, 0, NULL, 0); else err = if_newhead(&l3->inst.down, prim, dinfo, skb); return(err); }
static int do_disconnect(layer4_t *l4) { l4->cause_loc = CAUSE_LOC_PNET_LOCUSER; l4->cause_val = CAUSE_NORMAL_CLEARING; l4->progress = PROGRESS_TONE; if_link(l4->nst, man_down, MAN_CLEAR_CALL | REQUEST, l4->channel, 0, NULL, 0); return(0); }
static int connect_call(layer4_t *l4) { strcpy(l4->display,"connect ack"); if_link(l4->nst, man_down, MAN_CONNECT | RESPONSE, l4->channel, 0, NULL, 0); del_timer(&timer1); if (l4->sdata) do_connect(l4->sdata); return(0); }
int mISDN_l3up(l3_process_t *l3p, u_int prim, struct sk_buff *skb) { layer3_t *l3; int err = -EINVAL; if (!l3p) return(-EINVAL); l3 = l3p->l3; if (!skb) err = if_link(&l3->inst.up, prim, l3p->id, 0, NULL, 0); else err = if_newhead(&l3->inst.up, prim, l3p->id, skb); return(err); }
/* * Read a list of gateways from /etc/gateways and add them to our tables. * * This file contains a list of "remote" gateways. That is usually * a gateway which we cannot immediately determine if it is present or * not as we can do for those provided by directly connected hardware. * * If a gateway is marked "passive" in the file, then we assume it * does not understand RIP and assume it is always present. Those * not marked passive are treated as if they were directly connected * and assumed to be broken if they do not send us advertisements. * All remote interfaces are added to our list, and those not marked * passive are sent routing updates. * * A passive interface can also be local, hardware interface exempt * from RIP. */ void gwkludge(void) { #define STR2(x) #x #define STR(x) STR2(x) #define NETHOST_LEN 4 #define DNAME_LEN MAXHOSTNAMELEN #define GNAME_LEN MAXHOSTNAMELEN #define QUAL_LEN 8 FILE *fp; char *p, *lptr; const char *cp; char lbuf[PARMS_MAXLINELEN], net_host[NETHOST_LEN + 1]; char dname[MAXHOSTNAMELEN + 1]; char gname[MAXHOSTNAMELEN + 1], qual[QUAL_LEN +1]; struct interface *ifp; uint32_t dst, netmask, gate; int n; uint32_t lnum; struct stat sb; uint32_t state, metric; boolean_t default_dst; fp = fopen(PATH_GATEWAYS, "r"); if (fp == NULL) return; if (0 > fstat(fileno(fp), &sb)) { msglog("fstat() failed: %s for "PATH_GATEWAYS, rip_strerror(errno)); (void) fclose(fp); return; } for (lnum = 1; ; lnum++) { if (NULL == fgets(lbuf, sizeof (lbuf), fp)) break; /* Eliminate the /n character at the end of the lbuf */ if (strlen(lbuf) > 0) lbuf[strlen(lbuf) - 1] = '\0'; /* Move lptr to the first non-space character */ for (lptr = lbuf; isspace(*lptr); lptr++) ; if (*lptr == '#' || *lptr == '\0') continue; /* Move p to the end of the line */ p = lptr + strlen(lptr) - 1; /* Skip all trailing spaces except escaped space */ while (p > lptr && (isspace(*p) && *(p-1) != '\\')) p--; /* truncate the line to remove trailing spaces */ *++p = '\0'; /* notice newfangled parameter lines */ if (strncasecmp("net", lptr, 3) != 0 && strncasecmp("host", lptr, 4) != 0) { cp = parse_parms(lptr, (sb.st_uid == 0 && !(sb.st_mode&(S_IRWXG|S_IRWXO)))); if (cp != 0) msglog("%s in line %u of "PATH_GATEWAYS, cp, lnum); continue; } /* * Processes lines of the follwoing format: * net|host <name>[/mask] gateway <Gname> metric <value> * passive|active|extern */ qual[0] = '\0'; n = sscanf(lptr, "%"STR(NETHOST_LEN)"s %"STR(DNAME_LEN) "[^ \t] gateway %"STR(GNAME_LEN)"[^ / \t] metric %u %" STR(QUAL_LEN)"s\n", net_host, dname, gname, &metric, qual); if (n != 4 && n != 5) { msglog("bad "PATH_GATEWAYS" entry \"%s\"; %d values", lptr, n); continue; } if (metric >= HOPCNT_INFINITY) { msglog("bad metric in "PATH_GATEWAYS" entry \"%s\"", lptr); continue; } default_dst = _B_FALSE; if (strcasecmp(net_host, "host") == 0) { if (!gethost(dname, &dst)) { msglog("bad host \"%s\" in "PATH_GATEWAYS " entry \"%s\"", dname, lptr); continue; } netmask = HOST_MASK; } else if (strcasecmp(net_host, "net") == 0) { if (!getnet(dname, &dst, &netmask)) { msglog("bad net \"%s\" in "PATH_GATEWAYS " entry \"%s\"", dname, lptr); continue; } default_dst = (dst == RIP_DEFAULT); dst = htonl(dst); /* make network # into IP address */ } else { msglog("bad \"%s\" in "PATH_GATEWAYS " entry \"%s\"", net_host, lptr); continue; } if (!gethost(gname, &gate)) { msglog("bad gateway \"%s\" in "PATH_GATEWAYS " entry \"%s\"", gname, lptr); continue; } if (strcasecmp(qual, "passive") == 0) { /* * Passive entries are not placed in our tables, * only the kernel's, so we don't copy all of the * external routing information within a net. * Internal machines should use the default * route to a suitable gateway (like us). */ state = IS_REMOTE | IS_PASSIVE; if (metric == 0) metric = 1; } else if (strcasecmp(qual, "external") == 0) { /* * External entries are handled by other means * such as EGP, and are placed only in the daemon * tables to prevent overriding them with something * else. */ (void) strlcpy(qual, "external", sizeof (qual)); state = IS_REMOTE | IS_PASSIVE | IS_EXTERNAL; if (metric == 0) metric = 1; } else if (strcasecmp(qual, "active") == 0 || qual[0] == '\0') { if (default_dst) { msglog("bad net \"%s\" in "PATH_GATEWAYS " entry \"%s\"-- cannot be default", dname, lptr); continue; } if (metric != 0) { /* * Entries that are neither "passive" nor * "external" are "remote" and must behave * like physical interfaces. If they are not * heard from regularly, they are deleted. */ state = IS_REMOTE; } else { /* * "remote" entries with a metric of 0 * are aliases for our own interfaces */ state = IS_REMOTE | IS_PASSIVE | IS_ALIAS; } } else { msglog("bad "PATH_GATEWAYS" entry \"%s\";" " unknown type %s", lptr, qual); continue; } if (0 != (state & (IS_PASSIVE | IS_REMOTE))) state |= IS_NO_RDISC; if (state & IS_PASSIVE) state |= IS_NO_RIP; if (default_dst) { addroutefordefault(dst, gate, netmask, metric, ((state & IS_EXTERNAL)? RTS_EXTERNAL : 0)); continue; } ifp = check_dup(NULL, gate, dst, netmask, 0, _B_FALSE); if (ifp != NULL) { msglog("duplicate "PATH_GATEWAYS" entry \"%s\"", lptr); continue; } ifp = rtmalloc(sizeof (*ifp), "gwkludge()"); (void) memset(ifp, 0, sizeof (*ifp)); ifp->int_state = state; if (netmask == HOST_MASK) ifp->int_if_flags = IFF_POINTOPOINT | IFF_UP; else ifp->int_if_flags = IFF_UP; ifp->int_act_time = NEVER; ifp->int_addr = gate; ifp->int_dstaddr = dst; ifp->int_mask = netmask; ifp->int_ripv1_mask = netmask; ifp->int_std_mask = std_mask(gate); ifp->int_net = ntohl(dst); ifp->int_std_net = ifp->int_net & ifp->int_std_mask; ifp->int_std_addr = htonl(ifp->int_std_net); ifp->int_metric = metric; if (!(state & IS_EXTERNAL) && ifp->int_mask != ifp->int_std_mask) ifp->int_state |= IS_SUBNET; (void) snprintf(ifp->int_name, sizeof (ifp->int_name), "remote(%s)", gname); if_link(ifp, 0); } (void) fclose(fp); /* * After all of the parameter lines have been read, * apply them to any remote interfaces. */ for (ifp = ifnet; NULL != ifp; ifp = ifp->int_next) { get_parms(ifp); tot_interfaces++; if (!IS_RIP_OFF(ifp->int_state)) rip_interfaces++; if (!IS_RIP_OUT_OFF(ifp->int_state)) ripout_interfaces++; trace_if("Add", ifp); } }
static int l2up_create(layer2_t *l2, u_int prim, int dinfo, int len, void *arg) { return(if_link(l2->nst, l2->nst->l2_l3, prim, dinfo, len, arg, 0)); }