// delete an ipfw rule; // return SUCCESS on succes, ERROR on error int delete_rule(uint s, u_int32_t rule_number) { // Note: rule number is of type u_int16_t in ip_fw.h, // but a comment in ip_fw2.c shows that the expected size // when applying socket options is u_int32_t (see comment below) /* COMMENT FROM IP_FW2.C * * IP_FW_DEL is used for deleting single rules or sets, * and (ab)used to atomically manipulate sets. Argument size * is used to distinguish between the two: * sizeof(u_int32_t) * delete single rule or set of rules, * or reassign rules (or sets) to a different set. * 2*sizeof(u_int32_t) * atomic disable/enable sets. * first u_int32_t contains sets to be disabled, * second u_int32_t contains sets to be enabled. */ // do delete rule if(apply_socket_options(s, IP_FW_DEL, &rule_number, sizeof(rule_number)) < 0) { WARNING("Delete rule operation failed"); return ERROR; } return SUCCESS; }
// configure a dummynet pipe; // return SUCCESS on succes, ERROR on error int configure_pipe(int s, int pipe_nr, int bandwidth, int delay, int lossrate) { struct dn_pipe p; // reset data structure bzero(&p, sizeof(p)); // initialize appropriate fields p.pipe_nr = pipe_nr; p.fs.plr = lossrate; p.bandwidth = bandwidth; p.delay = delay; // set queue size to a small value to avoid large delays // in case bandwidth limitation is enforced p.fs.qsize = 2; if(apply_socket_options(s, IP_DUMMYNET_CONFIGURE, &p, sizeof(p)) < 0) { WARNING("Pipe configuration could not be applied"); return ERROR; } return SUCCESS; }
SOCKET open_listen_socket( unsigned short port ) { int res; SOCKET sck; sck = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); if (sck < 0) { throw runtime_error( "Unable to create listening socket" ); return -1; } apply_socket_options( sck ); #ifndef WIN32 int reuse_opt = 1; res = setsockopt( sck, SOL_SOCKET, SO_REUSEADDR, (const char *) &reuse_opt, sizeof(reuse_opt) ); if (res < 0) { throw runtime_error( "Unable to setsockopt (SO_REUSEADDR) on listening socket, res = " + decint(res) ); } #endif #define DISABLE_NAGLE_ALGORITHM 0 #if DISABLE_NAGLE_ALGORITHM int tcp_nodelay = -1; res = setsockopt( sck, IPPROTO_TCP, TCP_NODELAY, (const char *) &tcp_nodelay, sizeof(tcp_nodelay) ); if (res < 0) { cout << "Unable to setsockopt (TCP_NODELAY) on listening socket, res=" << res << endl; return -1; } #endif struct sockaddr_in connection; connection.sin_family = AF_INET; connection.sin_addr.s_addr = INADDR_ANY; connection.sin_port = ctBEu16( port ); res = bind( sck, (struct sockaddr *) &connection, sizeof connection ); if ( res < 0 ) { // Aug. 16, 2006. Austin // Added the port number that failed. string tmp_error = "Unable to bind listening socket. Port("+decint(port)+") Res="+decint(res); throw runtime_error(tmp_error); } res = listen( sck, SOMAXCONN ); if (res < 0) { throw runtime_error( "Listen failed, res=" + decint(res) ); } return sck; }
// add an ipfw rule containing a dummynet pipe to the firewall // return SUCCESS on succes, ERROR on error int add_rule(int s, uint16_t rulenum, int pipe_nr, char *src, char *dst, int direction) { int clen; in4_addr addr; uint16_t port; ipfw_insn cmd[10]; struct ip_fw *p; // additional rule length counter clen = 0; // process source address if(strncmp(src, "any", strlen(src))==0) { // source address was "any" cmd[clen].opcode = O_IP_SRC; cmd[clen].len = 0; cmd[clen].arg1 = 0; } else { if(atoaddr(src, &addr, &port) < 0) { WARNING("Invalid argument to add_rule: %s\n", src); return ERROR; } cmd[clen].opcode = O_IP_SRC; cmd[clen].len = 2; cmd[clen].arg1 = 0; ((uint32_t *)cmd)[clen + 1] = addr.word; clen += 2; if(port > 0) { cmd[clen].opcode = O_IP_SRCPORT; cmd[clen].len = 2; cmd[clen].arg1 = 0; ((uint32_t *)cmd)[clen + 1] = port | port << 16; clen += 2; } } // process destination address if(strncmp(dst, "any", strlen(dst))==0) { // destination address was "any" cmd[clen].opcode = O_IP_DST; cmd[clen].len = 0; cmd[clen].arg1 = 0; } else { if(atoaddr(dst, &addr, &port) < 0) { WARNING("Invalid argument to add_rule: %s", dst); return ERROR; } cmd[clen].opcode = O_IP_DST; cmd[clen].len = 2; cmd[clen].arg1 = 0; ((uint32_t *)cmd)[clen + 1] = addr.word; clen += 2; if(port > 0) { cmd[clen].opcode = O_IP_DSTPORT; cmd[clen].len = 2; cmd[clen].arg1 = 0; ((uint32_t *)cmd)[clen + 1] = port | port << 16; clen += 2; } } // use in/out direction indicators if(direction != DIRECTION_BOTH) { // basic command code for in/out operation cmd[clen].opcode = O_IN; cmd[clen].len = 1; // a negation mask is used for meaning "out" if(direction == DIRECTION_OUT) cmd[clen].len |= F_NOT; //printf("len=0x%x len&F_NOT=0x%x flen=%d\n", cmd[clen].len, cmd[clen].len & F_NOT, F_LEN(cmd+clen)); clen += 1; } // configure pipe cmd[clen].opcode = O_PIPE; cmd[clen].len = 2; cmd[clen].arg1 = pipe_nr; ((uint32_t *)cmd)[clen + 1] = 0; clen += 1; /* trick! */ if((p = (struct ip_fw *)malloc(sizeof(struct ip_fw) + clen * 4)) == NULL) { WARNING("Could not allocate memory for a new rule"); return ERROR; } bzero(p, sizeof(struct ip_fw)); p->act_ofs = clen - 1; p->cmd_len = clen + 1; p->rulenum = rulenum; bcopy(cmd, &p->cmd, clen * 4); // apply appropriate socket options if(apply_socket_options(s, IP_FW_ADD, p, sizeof(struct ip_fw) + clen*4) < 0) { WARNING("Adding rule operation failed"); return ERROR; } return 0; }