繁体   English   中英

将套接字绑定到具有UDP的特定接口? - C

[英]Bind a socket to a specific interface with UDP? - C

我想知道如何将套接字绑定到C中的特定接口。

我的@IP是XYZ3,网关是eth1上的XYZ1,但是如果我发送数据包,它将在回送接口上发送。

奇怪的是,如果我使用XYZ9(例如)作为IP源(而不是我的IP)来制作数据包,则它可以工作。

有什么线索吗?

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/time.h>

#define PCK_MAX_LEN  1024

#define IP_NAMESERV "172.20.10.1"
#define IP_ATTACKER "172.20.10.3"

#define PORT_QUERY   5555

pthread_cond_t ans_listen = PTHREAD_COND_INITIALIZER;
pthread_cond_t ans_receiv = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *fctThreadSendQuery      (void *arg); // Send 1 query to random.example.com
void *fctThreadListenResponse (void *arg); // Listen for response to that query

int main (void)
{
  pthread_t threadSendQuery;
  pthread_t threadListenResponse;

  pthread_create (&threadSendQuery, NULL, fctThreadSendQuery, NULL);
  pthread_create (&threadListenResponse, NULL, fctThreadListenResponse, NULL);

  pthread_join (threadListenResponse, NULL);
  pthread_join (threadSendQuery, NULL);

  return 0;
}


void *fctThreadSendQuery(void *arg) {
  unsigned int nQuery = 1;

  struct sockaddr_in *sin_attacker, *sin_resolver;
  sin_attacker = calloc(1, sizeof(struct sockaddr_in));
  sin_resolver = calloc(1, sizeof(struct sockaddr_in));

  sin_attacker->sin_family = AF_INET;
  sin_attacker->sin_addr.s_addr = inet_addr(IP_ATTACKER);
  sin_attacker->sin_port = htons(PORT_QUERY);

  int fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);

  bind(fd, sin_attacker, sizeof(struct sockaddr_in));

  sin_resolver->sin_family = AF_INET;
  sin_resolver->sin_addr.s_addr = inet_addr(IP_RESOLVER);
  sin_resolver->sin_port = htons(53);

  while (1) {
    // Now, we can build and send the query
    char *packet = calloc(PCK_MAX_LEN, sizeof(char));
    int pck_len = 0;
    int id = 0;

    char *target = calloc(16, sizeof(char));
    strcpy(target, randomTarget(nQuery-1));
    build_packet(IP_SRC, IP_DST, PORT_QUERY, 53, packet, &pck_len, target, NAME_LEN, id, QUERY);

    // Before sending the packet, we want to be sure that fctThreadListenResponse is listening
    pthread_mutex_lock (&mutex);
    puts("SEND: wait for RECV to LISTEN");
    pthread_cond_wait (&ans_listen, &mutex);
    puts("SEND: wait for RECV to LISTEN - OK");
    pthread_mutex_unlock(&mutex);
    sendto (fd, packet, pck_len, 0, sin_attacker, sizeof(struct sockaddr_in));
    puts("SEND: PCK SENT");

    pthread_mutex_lock (&mutex);
    puts("SEND: wait for RECV to RECV");
    pthread_cond_wait (&ans_receiv, &mutex);
    puts("SEND: wait for RECV to RECV - OK");
    pthread_mutex_unlock(&mutex);

    nQuery++;
    free(target);
    free(packet);
  }

  free(sin_resolver);
  free(sin_attacker);
  pthread_exit(NULL);
}

void *fctThreadListenResponse (void *arg) {
  usleep(100);
  struct sockaddr_in *sin_attacker, *sin_resolver;
  sin_attacker = calloc(1, sizeof(struct sockaddr_in));
  sin_resolver = calloc(1, sizeof(struct sockaddr_in));

  sin_attacker->sin_family = AF_INET;
  sin_attacker->sin_addr.s_addr = inet_addr(IP_ATTACKER);
  sin_attacker->sin_port = htons(PORT_QUERY);

  int fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);

  bind(fd, sin_attacker, sizeof(struct sockaddr_in));

  while (1) {
    char *packet = calloc(PCK_MAX_LEN, sizeof(char));
    unsigned int pck_len;

    pthread_mutex_lock (&mutex);
    pthread_cond_signal (&ans_listen);
    puts("RECV: LISTENING");
    pthread_mutex_unlock(&mutex);

    pck_len = recvfrom(fd, packet, PCK_MAX_LEN, 0, NULL, sin_resolver);
    puts("RECV: PCK RECEIVED");

    if (pck_len > 0) {
      pthread_mutex_lock (&mutex);
      pthread_cond_signal (&ans_receiv);
      pthread_mutex_unlock (&mutex);
    }

    free(packet);
  }
  pthread_exit(NULL);
}

我不知道build_packet是做什么的,但是sendto的文档仅列出了一些可能的原型,其中只有一个具有要使用的参数列表:

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
               const struct sockaddr *dest_addr, socklen_t addrlen);

在通话中,您可以使用:

sendto (fd, packet, pck_len, 0, sin_attacker, sizeof(struct sockaddr_in));

使用IP_ATTACKER(似乎是您自己的地址)配置了sin_attacker(dest_addr参数)的位置。 因此sendto可以看到托管在本地系统上的目标地址,并使用回送适配器发送数据包。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM