How WPAD works and how it works

Source: Internet
Author: User

How WPAD works and how it works

I. Introduction

Most proxy servers are used to connect to the INTERNET (International INTERNET) and INTRANET (Enterprise INTRANET ). Different Proxy Server parameters need to be set in multiple LAN to allow the browser to access the network. Functions in Microsoft Internet Explorer 5.0 or later versions already provide the function of automatically switching proxy servers. The network administrator needs to deploy the configuration file of the proxy server in advance, but the user's settings are very simple. This feature uses a protocol called "WPAD" (Web Proxy Auto-Discovery protocol.

 

Web Proxy Auto-Discovery Protocol (WPAD) allows the browser to automatically discover Proxy servers, making the Proxy server transparent to users, making it easy to access the Internet.

 

Reference: http://www.ibm.com/developerworks/cn/linux/1309_quwei_wpad/

 

II. Implementation

WPAD source code

/*************************************************************************** wpad.cpp** CREATE ON:  2013-03-14 * BY             :  Wayne Qu (qwquwei@cn.ibm.com)* * This demo is for Proxy auto defection(WPAD) feature development & UT. **************************************************************************/#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>#include <stdlib.h>#include <strings.h>#include <iostream>#include <string>#include <algorithm>#include <sstream>#include <sys/select.h>/* Useful definitions */#define DHCP_SERVER_PORT            67#define DHCP_CLIENT_PORT            68#define MAGIC_COOKIE                    0x63825363#define DHCP_INFORM                     8/* Sizes for DHCP options */#define MTU_MAX             1500#define DHCP_CHADDR_LEN         16#define SERVERNAME_LEN          64#define BOOTFILE_LEN            128#define DHCP_UDP_LEN            (14 + 20 + 8)#define DHCP_FIXED_LEN          (DHCP_UDP_LEN + 226)#define DHCP_OPTION_LEN         (MTU_MAX - DHCP_FIXED_LEN)/* DHCP options */enum DHO {    DHO_MESSAGETYPE            = 53,    DHO_PARAMETERREQUESTLIST   = 55,    DHO_PACFILELOCATION = 252,    DHO_END                    = 255};typedef struct dhcp_message_ {    uint8_t op;           /* message type */    uint8_t hwtype;       /* hardware address type */    uint8_t hwlen;        /* hardware address length */    uint8_t hwopcount;    /* should be zero in client message */    uint32_t xid;            /* transaction id */    uint16_t secs;           /* elapsed time in sec. from boot */    uint16_t flags;    uint32_t ciaddr;         /* (previously allocated) client IP */    uint32_t yiaddr;         /* 'your' client IP address */    uint32_t siaddr;         /* should be zero in client's messages */    uint32_t giaddr;         /* should be zero in client's messages */    uint8_t chaddr[DHCP_CHADDR_LEN];  /* client's hardware address */    uint8_t servername[SERVERNAME_LEN];    /* server host name */    uint8_t bootfile[BOOTFILE_LEN];    /* boot file name */    uint32_t cookie;    uint8_t options[DHCP_OPTION_LEN]; /* message options - cookie */}dhcp_message;void * xzalloc(size_t s){    void *value = malloc(s);    if (value != NULL)    {        bzero(value,s);    }    return value;}uint32_t GetIPV4Ciaddr(const std::string& ip_addr){    if( 3!=std::count(ip_addr.begin(), ip_addr.end(), '.') )    {        std::cout << "invalid IP Format : " << ip_addr;        return 0;    }    std::string::size_type beg = 0;    std::string::size_type end = 0;    std::string tmp_str[4];    uint32_t tmp_int[4];        for(int i=0; i<4; i++)    {        end = ip_addr.find(".", beg);        tmp_str[i] = ip_addr.substr(beg,end-beg);        tmp_int[i] = atoi(tmp_str[i].c_str());        if( tmp_int[i] > 255)        {            std::cout << "invalid IP Format : " << ip_addr;            return 0;        }        //std::cout<< tmp_int[i] << " ";        beg = end+1;    }        return (uint8_t)tmp_int[0] | ((uint8_t)tmp_int[1]<<8) | ((uint8_t)tmp_int[2]<<16) | ((uint8_t)tmp_int[3]<<24);}uint32_t GetCiaddr(const std::string& ip_addr){    //Just Ipv4 Now    return GetIPV4Ciaddr(ip_addr);}uint32_t GetChaddr(const std::string& mac_addr, uint8_t* chaddr){    if( 5!=std::count(mac_addr.begin(), mac_addr.end(), ':') )    {        std::cout << "invalid MAC Format : " << mac_addr;        return 0;    }    std::string::size_type beg = 0;    std::string::size_type end = 0;    std::string tmp_str[6];    uint32_t tmp_int[6];        for(int i=0; i<6; i++)    {        end = mac_addr.find(":", beg);        tmp_str[i] = mac_addr.substr(beg,end-beg);                std::stringstream tmp_stream;        tmp_stream << "0x" << tmp_str[i];        tmp_stream >> std::hex >> tmp_int[i];        if( tmp_int[i] > 255)        {            std::cout << "invalid MAC Format : " << mac_addr;            return 0;        }        chaddr[i] = tmp_int[i];        //std::cout<< std::hex << (int)chaddr[i] << " ";        beg = end+1;    }}//  Format: ipaddr - 9.125.90.117  macaddr E4:1F:13:DA:12:7Evoid make_message(const std::string& ip_addr, const std::string& mac_addr, dhcp_message **message){    dhcp_message* dhcp;    dhcp = (dhcp_message*)xzalloc(sizeof (*dhcp));    bzero(dhcp, sizeof(dhcp_message));        dhcp->op = 1;    dhcp->hwtype = 1;  //ARPHRD_ETHER    dhcp->hwlen = 6;    //MAC ADDR LENGTH    dhcp->xid = 1983;  //random    dhcp->ciaddr = GetCiaddr(ip_addr);    GetChaddr(mac_addr, dhcp->chaddr);        dhcp->cookie = htonl(MAGIC_COOKIE);    uint8_t *p = dhcp->options;    //option 53    *p++ = DHO_MESSAGETYPE;     *p++ = 1;    *p++ = DHCP_INFORM;    //option 55    *p++ = DHO_PARAMETERREQUESTLIST;     *p++ = 1;    *p++ = DHO_PACFILELOCATION;    *p++ = DHO_END;        *message = dhcp;}int open_send_socket(){    int sockfd;    struct sockaddr_in addr;    if((sockfd = socket(AF_INET,SOCK_DGRAM,0))<0)    {        //TBI    }    int  bBroadcast=1;    setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &bBroadcast, sizeof(bBroadcast));    return sockfd;}int open_recv_socket(char* ipaddr){    int sockfd;    struct sockaddr_in addr;    if((sockfd = socket(AF_INET,SOCK_DGRAM,0))<0)    {        std::cout << "setup socket failed" << std::endl;//TBI    }    bzero(&addr,sizeof(addr));    addr.sin_family = AF_INET;    addr.sin_port = htons(DHCP_CLIENT_PORT);    addr.sin_addr.s_addr = inet_addr(ipaddr);    const int retry_cnt = 10;    int retry_num = retry_cnt;    while(bind(sockfd, (struct sockaddr *)&addr, sizeof(addr))<0 && (retry_num > 0))    {        std::cout << "bind to " << ipaddr << ":" << DHCP_CLIENT_PORT<< " failed!"<<std::endl;//TBI        sleep(3);        --retry_num;    }    return sockfd;}int send_packet(int udp_fd, const uint8_t *data, ssize_t len){    struct sockaddr_in sin;    bzero(&sin, sizeof(sin));    sin.sin_family = AF_INET;    sin.sin_addr.s_addr=inet_addr("255.255.255.255");    sin.sin_port = htons(DHCP_SERVER_PORT);        return sendto(udp_fd, data, len, 0, (struct sockaddr *)&sin, sizeof(sin));}std::string dhcp_parser(uint8_t* options){    uint8_t* p = options;    int len;    std::string url;        while( (p-options) < DHCP_OPTION_LEN )    {        if( 252 == *p )        {            ++p;            len = *p++;            for( int i=0; i<len; ++i,++p)            {                url.push_back(*p);            }            std::cout << "find option 252 with length " << url.size() << std::endl;            break;        }        else if( 255 == *p )        {            break;        }        else        {            ++p;            len = *p++;            p+=len;             }    }    return url;}int readable_timeo(int sock_fd, int sec){    struct timeval tv_out;    tv_out.tv_sec = sec;    tv_out.tv_usec = 0;    setsockopt(sock_fd,SOL_SOCKET,SO_RCVTIMEO,&tv_out, sizeof(tv_out));}int main(int argc, char **argv){    dhcp_message *dhcp_send;    dhcp_message *dhcp_recv;    struct in_addr to;    struct timeval tv;    int send_socket_fd = open_send_socket();    int recv_socket_fd = open_recv_socket("9.125.90.177");        std::cout << "making DHCP message" << std::endl;    make_message("9.125.90.177", "E4:1F:13:DA:12:7E", &dhcp_send);    dhcp_recv = (dhcp_message*)xzalloc(sizeof (*dhcp_recv));    for(int i=0; i<3; ++i)    {        std::cout << "sending DHCP message" << std::endl;        if( -1 == send_packet(send_socket_fd, (uint8_t *)dhcp_send, sizeof(*dhcp_send)))        {            std::cout << "sendto() error" << std::endl;            continue;        }        struct sockaddr_in addr;        bzero(&addr, sizeof(addr));        int addr_len =sizeof(struct sockaddr_in);        std::cout << "receiving DHCP message" << std::endl;        readable_timeo(recv_socket_fd, 6);        if( -1 == recvfrom(recv_socket_fd, (uint8_t *)dhcp_recv, sizeof(*dhcp_recv), 0, (struct sockaddr*)&addr,(socklen_t*)&addr_len))        {            std::cout << "recvfrom() error" << std::endl;            continue;        }                break;    }/*    for(int i=0;i<100;i++)    {        std::cout << std::hex << int(dhcp_recv->options[i]) << " ";            }*/    std::cout << "dhcp->xid = " << dhcp_recv->xid << std::endl;    std::cout << "wpad url = " << dhcp_parser(dhcp_recv->options) << std::endl;    close(send_socket_fd);    close(recv_socket_fd);}

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.