int hepv3_message_parse(char *buf, unsigned int len, sip_msg_t* msg) { union sockaddr_union from; union sockaddr_union to; char *tmp; struct ip_addr dst_ip, src_ip; struct socket_info* si = 0; int i; char *payload = NULL; unsigned int payload_len = 0; struct hep_chunk *chunk; struct hep_generic_recv *hg; int totelem = 0; int chunk_vendor=0, chunk_type=0, chunk_length=0; int total_length = 0; int ret = 0; hg = (struct hep_generic_recv*)pkg_malloc(sizeof(struct hep_generic_recv)); if(hg==NULL) { LM_ERR("no more pkg memory left for hg\n"); return -1; } memset(hg, 0, sizeof(struct hep_generic_recv)); memset(heptime, 0, sizeof(struct hep_timehdr)); /* HEADER */ hg->header = (hep_ctrl_t *) (buf); /*Packet size */ total_length = ntohs(hg->header->length); dst_ip.af = 0; src_ip.af = 0; payload = NULL; correlation_id = NULL; authkey = NULL; i = sizeof(hep_ctrl_t); while(i < total_length) { /*OUR TMP DATA */ tmp = buf+i; chunk = (struct hep_chunk*) tmp; chunk_vendor = ntohs(chunk->vendor_id); chunk_type = ntohs(chunk->type_id); chunk_length = ntohs(chunk->length); /* if chunk_length */ if(chunk_length == 0) { /* BAD LEN we drop this packet */ goto error; } /* SKIP not general Chunks */ if(chunk_vendor != 0) { i+=chunk_length; } else { switch(chunk_type) { case 0: goto error; break; case 1: hg->ip_family = (hep_chunk_uint8_t *) (tmp); i+=chunk_length; totelem++; break; case 2: hg->ip_proto = (hep_chunk_uint8_t *) (tmp); i+=chunk_length; totelem++; break; case 3: hg->hep_src_ip4 = (hep_chunk_ip4_t *) (tmp); i+=chunk_length; src_ip.af=AF_INET; src_ip.len=4; src_ip.u.addr32[0] = hg->hep_src_ip4->data.s_addr; totelem++; break; case 4: hg->hep_dst_ip4 = (hep_chunk_ip4_t *) (tmp); i+=chunk_length; dst_ip.af=AF_INET; dst_ip.len=4; dst_ip.u.addr32[0] = hg->hep_dst_ip4->data.s_addr; totelem++; break; case 5: hg->hep_src_ip6 = (hep_chunk_ip6_t *) (tmp); i+=chunk_length; src_ip.af=AF_INET6; src_ip.len=16; memcpy(src_ip.u.addr, &hg->hep_src_ip6->data, 16); totelem++; break; case 6: hg->hep_dst_ip6 = (hep_chunk_ip6_t *) (tmp); i+=chunk_length; dst_ip.af=AF_INET6; dst_ip.len=16; memcpy(dst_ip.u.addr, &hg->hep_dst_ip6->data, 16); totelem++; break; case 7: hg->src_port = (hep_chunk_uint16_t *) (tmp); msg->rcv.src_port = ntohs(hg->src_port->data); i+=chunk_length; totelem++; break; case 8: hg->dst_port = (hep_chunk_uint16_t *) (tmp); msg->rcv.dst_port = ntohs(hg->dst_port->data); i+=chunk_length; totelem++; break; case 9: hg->time_sec = (hep_chunk_uint32_t *) (tmp); hg->time_sec->data = ntohl(hg->time_sec->data); heptime->tv_sec = hg->time_sec->data; i+=chunk_length; totelem++; break; case 10: hg->time_usec = (hep_chunk_uint32_t *) (tmp); hg->time_usec->data = ntohl(hg->time_usec->data); heptime->tv_usec = hg->time_usec->data; i+=chunk_length; totelem++; break; case 11: hg->proto_t = (hep_chunk_uint8_t *) (tmp); i+=chunk_length; totelem++; break; case 12: hg->capt_id = (hep_chunk_uint32_t *) (tmp); i+=chunk_length; heptime->captid = ntohs(hg->capt_id->data); totelem++; break; case 13: hg->keep_tm = (hep_chunk_uint16_t *) (tmp); i+=chunk_length; break; case 14: authkey = (char *) tmp + sizeof(hep_chunk_t); i+=chunk_length; break; case 15: hg->payload_chunk = (hep_chunk_t *) (tmp); payload = (char *) tmp+sizeof(hep_chunk_t); payload_len = chunk_length - sizeof(hep_chunk_t); i+=chunk_length; totelem++; break; case 17: correlation_id = (char *) tmp + sizeof(hep_chunk_t); i+=chunk_length; break; default: i+=chunk_length; break; } } } /* CHECK how much elements */ if(totelem < 9) { LM_ERR("Not all elements [%d]\n", totelem); goto done; } if ( dst_ip.af == 0 || src_ip.af == 0) { LM_ERR("NO IP's set\n"); goto done; } ip_addr2su(&to, &dst_ip, msg->rcv.dst_port); ip_addr2su(&from, &src_ip, msg->rcv.src_port); msg->rcv.src_su=from; su2ip_addr(&msg->rcv.src_ip, &from); su2ip_addr(&msg->rcv.dst_ip, &to); if(hg->ip_proto->data == IPPROTO_TCP) msg->rcv.proto=PROTO_TCP; else if(hg->ip_proto->data == IPPROTO_UDP) msg->rcv.proto=PROTO_UDP; if(payload != NULL) ret = len - payload_len; /*TIME*/ heptime->tv_sec = hg->time_sec->data; heptime->tv_usec = hg->time_usec->data; heptime->captid = ntohs(hg->capt_id->data); done: //if(si) pkg_free(si); if(hg) pkg_free(hg); return ret; error: if(si) pkg_free(si); if(hg) pkg_free(hg); return -1; }
int parsing_hepv3_message(char *buf, unsigned int len) { union sockaddr_union from; union sockaddr_union to; struct receive_info ri; char *tmp; struct ip_addr dst_ip, src_ip; struct socket_info* si = 0; int tmp_len, i; char *payload = NULL; unsigned int payload_len = 0; struct hep_chunk *chunk; struct hep_generic_recv *hg; int totelem = 0; int chunk_vendor=0, chunk_type=0, chunk_length=0; int total_length = 0; hg = (struct hep_generic_recv*)pkg_malloc(sizeof(struct hep_generic_recv)); if(hg==NULL) { LM_ERR("no more pkg memory left for hg\n"); return -1; } memset(hg, 0, sizeof(struct hep_generic_recv)); memset(heptime, 0, sizeof(struct hep_timehdr)); /* HEADER */ hg->header = (hep_ctrl_t *) (buf); /*Packet size */ total_length = ntohs(hg->header->length); ri.src_port = 0; ri.dst_port = 0; dst_ip.af = 0; src_ip.af = 0; payload = NULL; correlation_id = NULL; authkey = NULL; i = sizeof(hep_ctrl_t); while(i < total_length) { /*OUR TMP DATA */ tmp = buf+i; chunk = (struct hep_chunk*) tmp; chunk_vendor = ntohs(chunk->vendor_id); chunk_type = ntohs(chunk->type_id); chunk_length = ntohs(chunk->length); /* if chunk_length */ if(chunk_length == 0) { /* BAD LEN we drop this packet */ goto error; } /* SKIP not general Chunks */ if(chunk_vendor != 0) { i+=chunk_length; } else { switch(chunk_type) { case 0: goto error; break; case 1: hg->ip_family = (hep_chunk_uint8_t *) (tmp); i+=chunk_length; totelem++; break; case 2: hg->ip_proto = (hep_chunk_uint8_t *) (tmp); i+=chunk_length; totelem++; break; case 3: hg->hep_src_ip4 = (hep_chunk_ip4_t *) (tmp); i+=chunk_length; src_ip.af=AF_INET; src_ip.len=4; src_ip.u.addr32[0] = hg->hep_src_ip4->data.s_addr; totelem++; break; case 4: hg->hep_dst_ip4 = (hep_chunk_ip4_t *) (tmp); i+=chunk_length; dst_ip.af=AF_INET; dst_ip.len=4; dst_ip.u.addr32[0] = hg->hep_dst_ip4->data.s_addr; totelem++; break; case 5: hg->hep_src_ip6 = (hep_chunk_ip6_t *) (tmp); i+=chunk_length; src_ip.af=AF_INET6; src_ip.len=16; memcpy(src_ip.u.addr, &hg->hep_src_ip6->data, 16); totelem++; break; case 6: hg->hep_dst_ip6 = (hep_chunk_ip6_t *) (tmp); i+=chunk_length; dst_ip.af=AF_INET6; dst_ip.len=16; memcpy(dst_ip.u.addr, &hg->hep_dst_ip6->data, 16); totelem++; break; case 7: hg->src_port = (hep_chunk_uint16_t *) (tmp); ri.src_port = ntohs(hg->src_port->data); i+=chunk_length; totelem++; break; case 8: hg->dst_port = (hep_chunk_uint16_t *) (tmp); ri.dst_port = ntohs(hg->dst_port->data); i+=chunk_length; totelem++; break; case 9: hg->time_sec = (hep_chunk_uint32_t *) (tmp); hg->time_sec->data = ntohl(hg->time_sec->data); heptime->tv_sec = hg->time_sec->data; i+=chunk_length; totelem++; break; case 10: hg->time_usec = (hep_chunk_uint32_t *) (tmp); hg->time_usec->data = ntohl(hg->time_usec->data); heptime->tv_usec = hg->time_usec->data; i+=chunk_length; totelem++; break; case 11: hg->proto_t = (hep_chunk_uint8_t *) (tmp); i+=chunk_length; totelem++; break; case 12: hg->capt_id = (hep_chunk_uint32_t *) (tmp); i+=chunk_length; heptime->captid = ntohs(hg->capt_id->data); totelem++; break; case 13: hg->keep_tm = (hep_chunk_uint16_t *) (tmp); i+=chunk_length; break; case 14: authkey = (char *) tmp + sizeof(hep_chunk_t); i+=chunk_length; break; case 15: hg->payload_chunk = (hep_chunk_t *) (tmp); payload = (char *) tmp+sizeof(hep_chunk_t); payload_len = chunk_length - sizeof(hep_chunk_t); i+=chunk_length; totelem++; break; case 17: correlation_id = (char *) tmp + sizeof(hep_chunk_t); i+=chunk_length; break; default: i+=chunk_length; break; } } } /* CHECK how much elements */ if(totelem < 9) { LM_ERR("Not all elements [%d]\n", totelem); goto done; } if ( dst_ip.af == 0 || src_ip.af == 0) { LM_ERR("NO IP's set\n"); goto done; } ip_addr2su(&to, &dst_ip, ri.dst_port); ip_addr2su(&from, &src_ip, ri.src_port); ri.src_su=from; su2ip_addr(&ri.src_ip, &from); su2ip_addr(&ri.dst_ip, &to); if(hg->ip_proto->data == IPPROTO_TCP) ri.proto=PROTO_TCP; else if(hg->ip_proto->data == IPPROTO_UDP) ri.proto=PROTO_UDP; /* a little bit memory */ si=(struct socket_info*) pkg_malloc(sizeof(struct socket_info)); if (si==0) { LOG(L_ERR, "ERROR: new_sock_info: memory allocation error\n"); goto error; } memset(si, 0, sizeof(struct socket_info)); si->address = ri.dst_ip; si->socket=-1; /* set port & proto */ si->port_no = ri.dst_port; if(hg->ip_proto->data == IPPROTO_TCP) si->proto=PROTO_TCP; else if(hg->ip_proto->data == IPPROTO_UDP) si->proto=PROTO_UDP; si->flags=0; si->addr_info_lst=0; si->address_str.s = ip_addr2a(&si->address);; si->address_str.len = strlen(si->address_str.s); si->port_no_str.s = int2str(si->port_no, &tmp_len); si->port_no_str.len = tmp_len; si->address_str.len = strlen(si->address_str.s); si->name.len = si->address_str.len; si->name.s = si->address_str.s; ri.bind_address=si; /*TIME*/ heptime->tv_sec = hg->time_sec->data; heptime->tv_usec = hg->time_usec->data; heptime->captid = ntohs(hg->capt_id->data); if(payload != NULL ) { /* and now recieve message */ if (hg->proto_t->data == 5) receive_logging_json_msg(payload, payload_len, hg, "rtcp_capture"); else if (hg->proto_t->data == 32) receive_logging_json_msg(payload, payload_len, hg, "report_capture"); else if (hg->proto_t->data == 99) receive_logging_json_msg(payload, payload_len, hg, "report_capture"); else if (hg->proto_t->data == 100) receive_logging_json_msg(payload, payload_len, hg, "logs_capture"); else receive_msg(payload, payload_len, &ri); } done: if(si) pkg_free(si); if(hg) pkg_free(hg); return 1; error: if(si) pkg_free(si); if(hg) pkg_free(hg); return -1; }
/* receive an ipv4 udp packet over a raw socket. * The packet is copied in *buf and *buf is advanced to point to the * payload. Fills from and to. * @param rsock - raw socket * @param buf - the packet will be written to where *buf points intially and * then *buf will be advanced to point to the udp payload. * @param len - buffer length (should be enough to hold at least the * ip and udp headers + 1 byte). * @param from - result parameter, filled with source address and port of the * packet. * @param from - result parameter, filled with destination (local) address and * port of the packet. * @param rf - filter used to decide whether or not the packet is * accepted/processed. If null, all the packets are accepted. * @return packet len or <0 on error (-1 and -2 on recv error @see recvpkt4, * -3 if the headers are invalid and -4 if the packet doesn't * match the filter). */ int raw_udp4_recv(int rsock, char** buf, int len, union sockaddr_union* from, union sockaddr_union* to, struct raw_filter* rf) { int n; unsigned short dst_port; unsigned short src_port; struct ip_addr dst_ip; char* end; char* udph_start; char* udp_payload; struct ip iph; struct udphdr udph; unsigned short udp_len; n=recvpkt4(rsock, *buf, len, from, to); if (unlikely(n<0)) goto error; end=*buf+n; if (unlikely(n<((sizeof(struct ip) * raw_ipip ? 2 : 1)+sizeof(struct udphdr)))) { n=-3; goto error; } if(raw_ipip) *buf = *buf + sizeof(struct ip); /* FIXME: if initial buffer is aligned, one could skip the memcpy and directly cast ip and udphdr pointer to the memory */ memcpy(&iph, *buf, sizeof(struct ip)); udph_start=*buf+iph.ip_hl*4; udp_payload=udph_start+sizeof(struct udphdr); if (unlikely(udp_payload>end)){ n=-3; goto error; } memcpy(&udph, udph_start, sizeof(struct udphdr)); udp_len=ntohs(udph.uh_ulen); if (unlikely((udph_start+udp_len)!=end)){ if ((udph_start+udp_len)>end){ n=-3; goto error; }else{ ERR("udp length too small: %d/%d\n", (int)udp_len, (int)(end-udph_start)); n=-3; goto error; } } /* advance buf */ *buf=udp_payload; n=(int)(end-*buf); /* fill ip from the packet (needed if no PKT_INFO is used) */ dst_ip.af=AF_INET; dst_ip.len=4; dst_ip.u.addr32[0]=iph.ip_dst.s_addr; /* fill dst_port */ dst_port=ntohs(udph.uh_dport); ip_addr2su(to, &dst_ip, dst_port); /* fill src_port */ src_port=ntohs(udph.uh_sport); su_setport(from, src_port); if (likely(rf)) { su2ip_addr(&dst_ip, to); if ( (dst_port && rf->port1 && ((dst_port<rf->port1) || (dst_port>rf->port2)) ) || (matchnet(&dst_ip, &rf->dst)!=1) ){ /* no match */ n=-4; goto error; } } error: return n; }
/*! * \brief Convert a STR [proto:]ip[:port] into socket address. * [proto:]ip[:port] * \param pipport (udp:127.0.0.1:5060 or tcp:2001:0DB8:AC10:FE01:5060) * \param tmp_su target structure * \param proto uint protocol type * \return success / unsuccess */ static int pipport2su (str *sproto, str *ip, unsigned short port, union sockaddr_union *tmp_su, unsigned int *proto) { struct ip_addr *ip_a; str host_uri; /*parse protocol */ if(strncmp(sproto->s, "udp",3) == 0) *proto = IPPROTO_UDP; else if(strncmp(sproto->s, "tcp",3) == 0) *proto = IPPROTO_TCP; else if(strncmp(sproto->s, "tls",3) == 0) *proto = IPPROTO_IDP; /* fake proto type */ else if(strncmp(sproto->s, "sctp",4) == 0) *proto = IPPROTO_SCTP; else if(strncmp(sproto->s, "any",3) == 0) *proto = IPPROTO_UDP; else if(strncmp(sproto->s, "ws",2) == 0) *proto = IPPROTO_ESP; /* fake proto type */ else { LM_ERR("bad protocol %.*s\n", sproto->len, sproto->s); return -1; } /*check if ip is not null*/ if (ip->len == 0) { LM_ERR("malformed ip address\n"); return -1; } if (port == 0) { port = SIP_PORT; } else{ /*the address contains a port number*/ if (port<1024 || port>65536) { LM_ERR("invalid port number; must be in [1024,65536]\n"); return -1; } } LM_DBG("proto %d, host %.*s , port %d \n",*proto, ip->len, ip->s, port); /* now IPv6 address has no brakets. It should be fixed! */ host_uri = *ip; if (host_uri.s[0] == '[') { if(host_uri.s[host_uri.len-1] != ']') { LM_ERR("bracket not closed\n"); return -1; } host_uri.s++; host_uri.len -= 2; } /* check if it's an ip address */ if (((ip_a = str2ip(&host_uri)) != 0) || ((ip_a = str2ip6 (&host_uri)) != 0) ) { ip_addr2su(tmp_su, ip_a, ntohs(port)); return 0; } LM_ERR("host <%.*s> is not an IP\n",host_uri.len,host_uri.s); return -1; }
/*! * \brief Convert a STR [proto:]ip[:port] into socket address. * [proto:]ip[:port] * \param pipport (udp:127.0.0.1:5060 or tcp:2001:0DB8:AC10:FE01:5060) * \param tmp_su target structure * \param proto uint protocol type * \return success / unsuccess */ static int pipport2su (char *pipport, union sockaddr_union *tmp_su, unsigned int *proto) { unsigned int port_no, cutlen = 4; struct ip_addr *ip; char *p, *host_s; str port_str, host_uri; unsigned len = 0; char tmp_piport[256]; /*parse protocol */ if(strncmp(pipport, "udp:",4) == 0) *proto = IPPROTO_UDP; else if(strncmp(pipport, "tcp:",4) == 0) *proto = IPPROTO_TCP; else if(strncmp(pipport, "tls:",4) == 0) *proto = IPPROTO_IDP; /* fake proto type */ else if(strncmp(pipport, "ws:",3) == 0) *proto = IPPROTO_IDP; /* fake proto type */ else if(strncmp(pipport, "wss:",4) == 0) *proto = IPPROTO_IDP; /* fake proto type */ #ifdef USE_SCTP else if(strncmp(pipport, "sctp:",5) == 0) cutlen = 5, *proto = IPPROTO_SCTP; #endif else if(strncmp(pipport, "any:",4) == 0) *proto = IPPROTO_UDP; else { LM_ERR("bad protocol %s\n", pipport); return -1; } if((len = strlen(pipport)) >= 256) { LM_ERR("too big pipport\n"); goto error; } /* our tmp string */ strncpy(tmp_piport, pipport, len+1); len = 0; /*separate proto and host */ p = tmp_piport+cutlen; if( (*(p)) == '\0') { LM_ERR("malformed ip address\n"); goto error; } host_s=p; if( (p = strrchr(p+1, ':')) == 0 ) { LM_DBG("no port specified\n"); port_no = 0; } else { /*the address contains a port number*/ *p = '\0'; p++; port_str.s = p; port_str.len = strlen(p); LM_DBG("the port string is %s\n", p); if(str2int(&port_str, &port_no) != 0 ) { LM_ERR("there is not a valid number port\n"); goto error; } *p = '\0'; } /* now IPv6 address has no brakets. It should be fixed! */ if (host_s[0] == '[') { len = strlen(host_s + 1) - 1; if(host_s[len+1] != ']') { LM_ERR("bracket not closed\n"); goto error; } memmove(host_s, host_s + 1, len); host_s[len] = '\0'; } host_uri.s = host_s; host_uri.len = strlen(host_s); /* check if it's an ip address */ if (((ip=str2ip(&host_uri))!=0) || ((ip=str2ip6(&host_uri))!=0) ) { ip_addr2su(tmp_su, ip, ntohs(port_no)); return 0; } error: return -1; }