Ejemplo n.º 1
0
static int map_sip_addr(struct sk_buff **pskb, enum ip_conntrack_info ctinfo,
			struct nf_conn *ct, const char **dptr, size_t dlen,
			enum sip_header_pos pos, struct addr_map *map)
{
	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
	unsigned int matchlen, matchoff, addrlen;
	char *addr;

	if (ct_sip_get_info(ct, *dptr, dlen, &matchoff, &matchlen, pos) <= 0)
		return 1;

	if ((matchlen == map->addr[dir].srciplen ||
	     matchlen == map->addr[dir].srclen) &&
	    strncmp(*dptr + matchoff, map->addr[dir].src, matchlen) == 0) {
		addr    = map->addr[!dir].dst;
		addrlen = map->addr[!dir].dstlen;
	} else if ((matchlen == map->addr[dir].dstiplen ||
		    matchlen == map->addr[dir].dstlen) &&
		   strncmp(*dptr + matchoff, map->addr[dir].dst, matchlen) == 0) {
		addr    = map->addr[!dir].src;
		addrlen = map->addr[!dir].srclen;
	} else
		return 1;

	if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo,
				      matchoff, matchlen, addr, addrlen))
		return 0;
	*dptr = (*pskb)->data + ip_hdrlen(*pskb) + sizeof(struct udphdr);
	return 1;

}
Ejemplo n.º 2
0
static unsigned int mangle_packet(struct sk_buff *skb, unsigned int protoff,
                                  unsigned int dataoff,
                                  const char **dptr, unsigned int *datalen,
                                  unsigned int matchoff, unsigned int matchlen,
                                  const char *buffer, unsigned int buflen)
{
    enum ip_conntrack_info ctinfo;
    struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
    struct tcphdr *th;
    unsigned int baseoff;

    if (nf_ct_protonum(ct) == IPPROTO_TCP) {
        th = (struct tcphdr *)(skb->data + protoff);
        baseoff = protoff + th->doff * 4;
        matchoff += dataoff - baseoff;

        if (!__nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
                                        protoff, matchoff, matchlen,
                                        buffer, buflen, false))
            return 0;
    } else {
        baseoff = protoff + sizeof(struct udphdr);
        matchoff += dataoff - baseoff;

        if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo,
                                      protoff, matchoff, matchlen,
                                      buffer, buflen))
            return 0;
    }

    /* Reload data pointer and adjust datalen value */
    *dptr = skb->data + dataoff;
    *datalen += buflen - matchlen;
    return 1;
}
Ejemplo n.º 3
0
static int mangle_content_len(struct sk_buff **pskb,
			      enum ip_conntrack_info ctinfo,
			      struct nf_conn *ct,
			      const char *dptr)
{
	unsigned int dataoff, matchoff, matchlen;
	char buffer[sizeof("65536")];
	int bufflen;

	dataoff = ip_hdrlen(*pskb) + sizeof(struct udphdr);

	/* Get actual SDP lenght */
	if (ct_sip_get_info(ct, dptr, (*pskb)->len - dataoff, &matchoff,
			    &matchlen, POS_SDP_HEADER) > 0) {

		/* since ct_sip_get_info() give us a pointer passing 'v='
		   we need to add 2 bytes in this count. */
		int c_len = (*pskb)->len - dataoff - matchoff + 2;

		/* Now, update SDP length */
		if (ct_sip_get_info(ct, dptr, (*pskb)->len - dataoff, &matchoff,
				    &matchlen, POS_CONTENT) > 0) {

			bufflen = sprintf(buffer, "%u", c_len);
			return nf_nat_mangle_udp_packet(pskb, ct, ctinfo,
							matchoff, matchlen,
							buffer, bufflen);
		}
	}
	return 0;
}
Ejemplo n.º 4
0
static int set_addr(struct sk_buff **pskb,
		    unsigned char **data, int dataoff,
		    unsigned int addroff, __be32 ip, __be16 port)
{
	enum ip_conntrack_info ctinfo;
	struct nf_conn *ct = nf_ct_get(*pskb, &ctinfo);
	struct {
		__be32 ip;
		__be16 port;
	} __attribute__ ((__packed__)) buf;
	struct tcphdr _tcph, *th;

	buf.ip = ip;
	buf.port = port;
	addroff += dataoff;

	if (ip_hdr(*pskb)->protocol == IPPROTO_TCP) {
		if (!nf_nat_mangle_tcp_packet(pskb, ct, ctinfo,
					      addroff, sizeof(buf),
					      (char *) &buf, sizeof(buf))) {
			if (net_ratelimit())
				printk("nf_nat_h323: nf_nat_mangle_tcp_packet"
				       " error\n");
			return -1;
		}

		/* Relocate data pointer */
		th = skb_header_pointer(*pskb, ip_hdrlen(*pskb),
					sizeof(_tcph), &_tcph);
		if (th == NULL)
			return -1;
		*data = (*pskb)->data + ip_hdrlen(*pskb) +
		    th->doff * 4 + dataoff;
	} else {
		if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo,
					      addroff, sizeof(buf),
					      (char *) &buf, sizeof(buf))) {
			if (net_ratelimit())
				printk("nf_nat_h323: nf_nat_mangle_udp_packet"
				       " error\n");
			return -1;
		}
		/* nf_nat_mangle_udp_packet uses skb_make_writable() to copy
		 * or pull everything in a linear buffer, so we can safely
		 * use the skb pointers now */
		*data = ((*pskb)->data + ip_hdrlen(*pskb) +
			 sizeof(struct udphdr));
	}

	return 0;
}
Ejemplo n.º 5
0
static unsigned int mangle_packet(struct sk_buff *skb,
                  const char **dptr, unsigned int *datalen,
                  unsigned int matchoff, unsigned int matchlen,
                  const char *buffer, unsigned int buflen)
{
    enum ip_conntrack_info ctinfo;
    struct nf_conn *ct = nf_ct_get(skb, &ctinfo);

    if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, matchoff, matchlen,
                      buffer, buflen))
        return 0;

    /* Reload data pointer and adjust datalen value */
    *dptr = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr);
    *datalen += buflen - matchlen;
    return 1;
}
Ejemplo n.º 6
0
static unsigned int help(struct sk_buff *skb,
			 enum ip_conntrack_info ctinfo,
			 unsigned int matchoff,
			 unsigned int matchlen,
			 struct nf_conntrack_expect *exp)
{
	char buffer[sizeof("65535")];
	u_int16_t port;
	unsigned int ret;

	/* Connection comes from client. */
	exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
	exp->dir = IP_CT_DIR_ORIGINAL;

	/* When you see the packet, we need to NAT it the same as the
	 * this one (ie. same IP: it will be TCP and master is UDP). */
	exp->expectfn = nf_nat_follow_master;

	/* Try to get same port: if not, try to change it. */
	for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
		int ret;

		exp->tuple.dst.u.tcp.port = htons(port);
		ret = nf_ct_expect_related(exp);
		if (ret == 0)
			break;
		else if (ret != -EBUSY) {
			port = 0;
			break;
		}
	}

	if (port == 0)
		return NF_DROP;

	sprintf(buffer, "%u", port);
	ret = nf_nat_mangle_udp_packet(skb, exp->master, ctinfo,
				       matchoff, matchlen,
				       buffer, strlen(buffer));
	if (ret != NF_ACCEPT)
		nf_ct_unexpect_related(exp);
	return ret;
}
Ejemplo n.º 7
0
static unsigned int mangle_sip_packet(struct sk_buff **pskb,
				      enum ip_conntrack_info ctinfo,
				      struct nf_conn *ct,
				      const char **dptr, size_t dlen,
				      char *buffer, int bufflen,
				      enum sip_header_pos pos)
{
	unsigned int matchlen, matchoff;

	if (ct_sip_get_info(ct, *dptr, dlen, &matchoff, &matchlen, pos) <= 0)
		return 0;

	if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo,
				      matchoff, matchlen, buffer, bufflen))
		return 0;

	/* We need to reload this. Thanks Patrick. */
	*dptr = (*pskb)->data + ip_hdrlen(*pskb) + sizeof(struct udphdr);
	return 1;
}