static int udp_sendmsg(struct sock *sk, struct msghdr *msg, int flags) { int ret; size_t data_len, total_len, actual_len; struct sk_buff *skb; const struct sockaddr_in *to; const struct sockaddr *sockaddr; assert(sk); assert(sk->o_ops); assert(sk->o_ops->make_pack); assert(msg); assert(msg->msg_iov); assert(msg->msg_iov->iov_base); data_len = msg->msg_iov->iov_len; total_len = actual_len = UDP_HEADER_SIZE + data_len; skb = NULL; sockaddr = (const struct sockaddr *)msg->msg_name; ret = sk->o_ops->make_pack(sk, sockaddr, &actual_len, &skb); if (ret != 0) { return ret; } #if 0 if (actual_len < total_len) { skb_free(skb); return -EMSGSIZE; } #endif if (msg->msg_name != NULL) { to = (const struct sockaddr_in *)msg->msg_name; } else { to = (const struct sockaddr_in *)&to_inet_sock(sk)->dst_in; } assert(skb); assert(skb->h.uh); udp_build(skb->h.uh, sock_inet_get_src_port(sk), to->sin_port, total_len); memcpy(skb->h.uh + 1, msg->msg_iov->iov_base, data_len); udp4_set_check_field(skb->h.uh, skb->nh.iph); assert(sk->o_ops->snd_pack); ret = sk->o_ops->snd_pack(skb); if (0 > ret) { return ret; } return data_len; }
int main() { int sock; // RAW сокет struct sockaddr_ll addr; // Данные назначения для физического уровня u_char *data; // Данные для следующего уровня int psize; // Размер данных // Создаем RAW сокет sock = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW); if (sock == -1){ perror("ERROR create RAW socket"); exit(-1); } // Обворачиваем заголовком транспортного уровня data = udp_build(SRC_IP, DST_IP, SRC_PORT, DST_PORT, MSG, strlen(MSG)); psize = strlen(MSG) + sizeof(struct header_udp); // Обворачиваем заголовком сетевого уровня data = ipv4_build(SRC_IP, DST_IP, data, psize); psize += sizeof(struct header_ipv4); // Обворачиваем заголовком канального уровня u_char smac[] = {0x48, 0x5b, 0x39, 0x7a, 0xcf, 0x7f}; // MAC источника u_char dmac[] = {0x38, 0x63, 0xbb, 0xae, 0xcc, 0xbc}; // MAC назначения data = eth_build(dmac, smac, data, psize); psize += sizeof(struct header_eth); //Отправляем memset(&addr, 0, sizeof(addr)); addr.sll_family = AF_PACKET; addr.sll_ifindex = 2; addr.sll_halen = 6; memcpy(addr.sll_addr, dmac, 6); //printf("INDEX: %d", if_nametoindex("enp3s0")); if (sendto(sock, data, psize, 0, (struct sockaddr *)&addr, sizeof(addr)) == -1) { perror("sendto"); close(sock); exit(-1); } return 0; }