raw socket编程

/*
 *      Function: RAW socket utility routines implementation:
 *
 *      File Name: raw_gen.c
 *      Copyright by: no copyright
 *      Created by: Dangdanding
 *
 *      Platform: Linux
 *      Version: 0.1v
 *      Make: gcc -Wall -c -DLINUX raw_gen.c
 *      ChangeLog:
 */


#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/udp.h>

#if defined(LINUX)
#include <linux/tcp.h>
#else
#include <netinet/tcp.h>
#endif

#include "raw_gen.h"
#include "error.h"

//for LINUX
#ifndef IP_LEN_HORDER
#define IP_LEN_HORDER
#endif

/* psuedo header for UDP and TCP */
struct psuedohdr  {
  struct in_addr source_address;
  struct in_addr dest_address;
  unsigned char place_holder;
  unsigned char protocol;
  unsigned short length;
} psuedohdr;


/* Write out an IP header.*/
void ip_gen(char *packet,unsigned char protocol,struct in_addr saddr,
            struct in_addr daddr,unsigned short length)
{
#if !defined(LINUX)
  struct ip *iphdr;
#else
  struct iphdr *iphdr;
#endif /* LINUX */

#if !defined(LINUX)
  iphdr = (struct ip *)packet;
  memset((char *)iphdr,'/0',sizeof(struct ip));
 
  iphdr->ip_hl = 5;
  iphdr->ip_v = IPVERSION;
 
#ifdef IP_LEN_HORDER
  iphdr->ip_len = length;
#else
  iphdr->ip_len = htons(length);
#endif /* IP_LEN_HORDER */

  iphdr->ip_id = htons(getpid());
  iphdr->ip_ttl = DEFAULT_TTL;
  iphdr->ip_p = protocol;

  iphdr->ip_src = saddr;
  iphdr->ip_dst = daddr;
 
  iphdr->ip_sum = (unsigned short)in_cksum((unsigned short *)iphdr,
                                           sizeof(struct ip));
 
#else /* LINUX */
 
  iphdr = (struct iphdr *)packet;
  memset((char *)iphdr,'/0',sizeof(struct iphdr));
 
  iphdr->ihl = 5;
  iphdr->version = IPVERSION;
   
#ifdef IP_LEN_HORDER
  iphdr->tot_len = length;
#else
  iphdr->tot_len = htons(length);
#endif /* IP_LEN_HORDER */
 
  //iphdr->id = htons(getpid());
  iphdr->id = htons(random());
  iphdr->ttl = DEFAULT_TTL;
  iphdr->protocol = protocol;

  iphdr->saddr = saddr.s_addr;
  iphdr->daddr = daddr.s_addr;

  iphdr->check = (unsigned short)in_cksum((unsigned short *)iphdr,
                                          sizeof(struct iphdr));
#endif /* LINUX */
  return;
} /* ip_gen() */

/* Write out a TCP header */
void tcp_gen(char *packet,unsigned short sport, unsigned short dport,
             unsigned long seq, unsigned long ackseq,
             u_int16_t fin,
             u_int16_t syn,
             u_int16_t rst,
             u_int16_t ack,
             u_int16_t psh,
             u_int16_t urg)
{
  struct tcphdr *tcp;
 
  tcp = (struct tcphdr *)packet;
  memset((char *)tcp,'/0',sizeof(struct tcphdr));

#if !defined(LINUX)
  tcp->th_sport = htons(sport);
  tcp->th_dport = htons(dport);
 
  tcp->th_seq = htonl(seq);
  tcp->th_ack = htonl(ack);
 
#ifdef X2_OFF
  tcp->th_x2_off = TH_OFFSET;
#else /* X2_OFF */
  tcp->th_off = TH_OFFSET;
  tcp->th_x2 = 0;
#endif /* X2_OFF */

  tcp->th_win = htons(TCP_WINDOW_SIZE);
  tcp->th_flags = TH_FIN;
 
#else /* LINUX */

  tcp->source = htons(sport);
  tcp->dest = htons(dport);
 
  tcp->seq = htonl(seq);
  tcp->ack_seq = htonl(ackseq);
 
  tcp->res1 = 0;
  tcp->doff = TH_OFFSET;

  tcp->window = htons(TCP_WINDOW_SIZE);

  tcp->fin = fin;
  tcp->syn = syn;
  tcp->ack = ack;
  tcp->psh = psh;
  tcp->urg = rst;
  tcp->urg = urg;

#endif /* LINUX */

  return;
} /* tcp_gen() */

/* Write UDP header */
void udp_gen(char *packet,unsigned short sport,
             unsigned short dport,unsigned short length)
{
  struct udphdr *udp;
 
  udp = (struct udphdr *)packet;

#if !defined(LINUX)
  udp->uh_sport = htons(sport);
  udp->uh_dport = htons(dport);
  udp->uh_ulen =  htons(length);
  udp->uh_sum = 0;
 
#else /* LINUX */
  udp->source = htons(sport);
  udp->dest = htons(dport);
  udp->len = htons(length);
  udp->check = 0;

#endif /* LINUX */
 
  return;
} /* udp_gen() */

/* transport layer header checksum */
unsigned short trans_check(unsigned char proto,
                           char *packet,
                           int length,
                           struct in_addr source_address,
                           struct in_addr dest_address)
{
  char *psuedo_packet;
  unsigned short answer;
 
  psuedohdr.protocol = proto;
  psuedohdr.length = htons(length);
  psuedohdr.place_holder = 0;

  psuedohdr.source_address = source_address;
  psuedohdr.dest_address = dest_address;
 
  if((psuedo_packet = malloc(sizeof(psuedohdr) + length)) == NULL)  {
    perror("malloc");
    exit(1);
  }
 
  memcpy(psuedo_packet,&psuedohdr,sizeof(psuedohdr));
  memcpy((psuedo_packet + sizeof(psuedohdr)),
         packet,length);
 
  answer = (unsigned short)in_cksum((unsigned short *)psuedo_packet,
                                    (length + sizeof(psuedohdr)));
  free(psuedo_packet);
  return answer;
} /* trans_check() */

/*
 * in_cksum --
 *      Checksum routine for Internet Protocol family headers (C Version)
 *
 *
 * Copyright (c) 1989, 1993
 *      The Regents of the University of California.  All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * Mike Muuss.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed by the University of
 *      California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

unsigned short in_cksum(const unsigned short *addr,int len)
{
        register int sum = 0;
        u_short answer = 0;
        const register u_short *w = addr;
        register int nleft = len;

        /*
         * Our algorithm is simple, using a 32 bit accumulator (sum), we add
         * sequential 16 bit words to it, and at the end, fold back all the
         * carry bits from the top 16 bits into the lower 16 bits.
         */
        while (nleft > 1)  {
                sum += *w++;
                nleft -= 2;
        }

        /* mop up an odd byte, if necessary */
        if (nleft == 1) {
                *(u_char *)(&answer) = *(u_char *)w ;
                sum += answer;
        }

        /* add back carry outs from top 16 bits to low 16 bits */
        sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
        sum += (sum >> 16);                     /* add carry */
        answer = ~sum;                          /* truncate to 16 bits */
        return(answer);
}

extern void icmp_echo_gen(char *packet, uint8_t type, uint16_t id, uint16_t sequence, uint16_t datalen)
{

        int     len;
        struct icmphdr  *icmphdr = (struct icmphdr *)packet;

        bzero(icmphdr, ICMPHDRS);
        icmphdr->type = type;
        //icmphdr->code = 0;
        icmphdr->un.echo.sequence =  sequence;
        icmphdr->un.echo.id = id;

        len = ICMPHDRS + datalen;
        icmphdr->checksum = in_cksum((unsigned short *)icmphdr, len);

        return;
}//generate icmp ECHO datagram

extern int get_raw_socket()
{
        int     sockfd;
        int     on      =1;//for setsockopt()

        if (-1 == (sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW))) {
                err_sys("send_raw_tcp: ", "socket() error!");
        }

        //set ip options
        if (setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)) < 0) {
                err_sys("send_raw_tcp: ", "setsockopt() error!");
        }

        return sockfd;
}//end of get_raw_socket() 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值