int main(void) { static int fd[MAX_PAR]; /* to force initialization */ struct sockaddr_atmsvc local[MAX_ADDR]; struct atmif_sioc req; struct atm_sap sap; struct atm_qos qos; int listen_fd; fd_set rset,wset; int fds,completed = 0,connects = 0,accepts = 0; FD_ZERO(&rset); FD_ZERO(&wset); if (text2sap(SAP,&sap,0) < 0) { fprintf(stderr,"text2sap\n"); return 1; } if (text2qos(QOS,&qos,0) < 0) { fprintf(stderr,"text2qos\n"); return 1; } listen_fd = socket(PF_ATMSVC,SOCK_DGRAM,0); if (listen_fd < 0) { perror("socket"); return 1; } req.number = ITF; req.arg = local; req.length = sizeof(local); if (ioctl(listen_fd,ATM_GETADDR,&req) < 0) { perror("ioctl"); return 1; } if (!req.length) { fprintf(stderr,"No local address\n"); return 1; } if (setsockopt(listen_fd,SOL_ATM,SO_ATMSAP,&sap,sizeof(sap)) < 0) { perror("setsockopt SO_ATMSAP"); return 1; } if (setsockopt(listen_fd,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) { perror("setsockopt SO_ATMQOS"); return 1; } if (bind(listen_fd,(struct sockaddr *) local,sizeof(*local)) < 0) { perror("bind"); return 1; } if (fcntl(listen_fd,F_SETFL,O_NONBLOCK) < 0) { perror("fnctl"); return 1; } if (listen(listen_fd,5) < 0) { perror("listen"); return 1; } FD_SET(listen_fd,&rset); fds = listen_fd+1; (void) signal(SIGCHLD,SIG_IGN); while (1) { static struct timeval no_delay; fd_set _rset = rset; fd_set _wset = wset; int ret,i,empty; no_delay.tv_sec = 0; no_delay.tv_usec = 100000; ret = select(fds,&_rset,&_wset,NULL,&no_delay); if (ret < 0) { perror("select"); return 1; } if (FD_ISSET(listen_fd,&_rset)) { pid_t pid; pid = fork(); if (pid < 0) { perror("fork"); return 1; } if (!pid) { if (accept(listen_fd,NULL,NULL) >= 0) exit(0); perror("accept"); return 1; } accepts++; } empty = -1; for (i = 0; i < MAX_PAR; i++) if (!fd[i]) empty = i; else if (FD_ISSET(fd[i],&_wset)) { struct sockaddr_atmsvc dummy; if (connect(fd[i],(struct sockaddr *) &dummy,sizeof(dummy)) < 0) { perror("connect"); return 1; } FD_CLR(fd[i],&wset); fd[i] = 0; empty = i; if (++completed == EXIT_LIM) { printf("%d attempted, %d completed, %d accepts\n", connects,completed,accepts); return 0; } } if (empty != -1) { fd[empty] = socket(PF_ATMSVC,SOCK_DGRAM,0); if (fd[empty] < 0) { perror("socket"); return 1; } if (fcntl(fd[empty],F_SETFL,O_NONBLOCK) < 0) { perror("fnctl"); return 1; } if (setsockopt(fd[empty],SOL_ATM,SO_ATMSAP,&sap,sizeof(sap)) < 0) { perror("setsockopt SO_ATMSAP"); return 1; } if (setsockopt(fd[empty],SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) { perror("setsockopt SO_ATMQOS"); return 1; } if (connect(fd[empty],(struct sockaddr *) local,sizeof(*local)) < 0 && errno != EINPROGRESS) { perror("connect"); return 1; } FD_SET(fd[empty],&wset); if (fds <= fd[empty]) fds = fd[empty]+1; connects++; } } return 0; }
static int atm_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) { struct sockaddr_atmsvc addr; struct atm_qos qos; struct atm_sap sap; unsigned char hdr[MAX_HDR_LEN]; __u32 excess = 0; struct rtattr *tail; int sndbuf = 0; int hdr_len = -1; int set_clip = 0; int s; memset(&addr,0,sizeof(addr)); (void) text2qos("aal5,ubr:sdu=9180,rx:none",&qos,0); (void) text2sap("blli:l2=iso8802",&sap,0); while (argc > 0) { if (!strcmp(*argv,"pvc")) { NEXT_ARG(); if (text2atm(*argv,(struct sockaddr *) &addr, sizeof(addr),T2A_PVC | T2A_NAME) < 0) { explain(); return -1; } } else if (!strcmp(*argv,"svc")) { NEXT_ARG(); if (text2atm(*argv,(struct sockaddr *) &addr, sizeof(addr),T2A_SVC | T2A_NAME) < 0) { explain(); return -1; } } else if (!strcmp(*argv,"qos")) { NEXT_ARG(); if (text2qos(*argv,&qos,0) < 0) { explain(); return -1; } } else if (!strcmp(*argv,"sndbuf")) { char *end; NEXT_ARG(); sndbuf = strtol(*argv,&end,0); if (*end) { explain(); return -1; } } else if (!strcmp(*argv,"sap")) { NEXT_ARG(); if (addr.sas_family != AF_ATMSVC || text2sap(*argv,&sap,T2A_NAME) < 0) { explain(); return -1; } } else if (!strcmp(*argv,"hdr")) { unsigned char *ptr; char *walk; NEXT_ARG(); ptr = hdr; for (walk = *argv; *walk; walk++) { int tmp; if (ptr == hdr+MAX_HDR_LEN) { // fprintf(stderr,"header is too long\n"); return -1; } if (*walk == '.') continue; if (!isxdigit(walk[0]) || !walk[1] || !isxdigit(walk[1])) { explain(); return -1; } sscanf(walk,"%2x",&tmp); *ptr++ = tmp; walk++; } hdr_len = ptr-hdr; } else if (!strcmp(*argv,"excess")) { NEXT_ARG(); if (!strcmp(*argv,"clp")) excess = 0; else if (get_tc_classid(&excess,*argv)) { explain(); return -1; } } else if (!strcmp(*argv,"clip")) { set_clip = 1; } else { explain(); return 1; } argc--; argv++; } s = socket(addr.sas_family,SOCK_DGRAM,0); if (s < 0) { // perror("socket"); return -1; } if (setsockopt(s,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) { // perror("SO_ATMQOS"); return -1; } if (sndbuf) if (setsockopt(s,SOL_SOCKET,SO_SNDBUF,&sndbuf,sizeof(sndbuf)) < 0) { // perror("SO_SNDBUF"); return -1; } if (addr.sas_family == AF_ATMSVC && setsockopt(s,SOL_ATM,SO_ATMSAP, &sap,sizeof(sap)) < 0) { // perror("SO_ATMSAP"); return -1; } if (connect(s,(struct sockaddr *) &addr,addr.sas_family == AF_ATMPVC ? sizeof(struct sockaddr_atmpvc) : sizeof(addr)) < 0) { /// perror("connect"); return -1; } if (set_clip) if (ioctl(s,ATMARP_MKIP,0) < 0) { // perror("ioctl ATMARP_MKIP"); return -1; } tail = NLMSG_TAIL(n); addattr_l(n,1024,TCA_OPTIONS,NULL,0); addattr_l(n,1024,TCA_ATM_FD,&s,sizeof(s)); if (excess) addattr_l(n,1024,TCA_ATM_EXCESS,&excess,sizeof(excess)); if (hdr_len != -1) addattr_l(n,1024,TCA_ATM_HDR,hdr,hdr_len); tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; return 0; }