Created
January 3, 2025 13:35
-
-
Save phhusson/87c42bc100f78cbdce9e92ec649d7096 to your computer and use it in GitHub Desktop.
dhcp-inform for sip server ( = get p-cscf server for ims)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <arpa/inet.h> | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
#include <netinet/udp.h> | |
#include <ifaddrs.h> | |
#include <net/if.h> | |
#define DHCPV6_CLIENT_PORT 546 | |
#define DHCPV6_SERVER_PORT 547 | |
#define DHCPV6_MULTICAST_GROUP "FF02::1:2" | |
#define DHCPV6_INFORMATION_REQUEST 11 | |
#define DHCPV6_DNS_SERVERS 23 | |
#define DHCPV6_DOMAIN_LIST 24 | |
#define SIP_SERVER_D 21 | |
#define SIP_SERVER_A 22 | |
#define OPTION_REQUEST_OPTION 6 | |
// Function to create a DHCPv6 Information Request packet | |
int create_dhcpv6_info_request(unsigned char *packet) { | |
// DHCPv6 Message Type (Information Request) | |
int i = 0; | |
packet[i++] = 1;//solicit 11; // information request | |
// Transaction ID (random 3 bytes) | |
packet[i++] = rand(); | |
packet[i++] = rand(); | |
packet[i++] = rand(); | |
// Options | |
// Option: DNS Servers (23) | |
#if 0 | |
packet[i++] = (DHCPV6_DNS_SERVERS >> 8) & 0xFF; | |
packet[i++] = DHCPV6_DNS_SERVERS & 0xFF; | |
packet[i++] = 0x00; // Length (0 for now, will be filled later) | |
packet[i++] = 0x00; | |
// Option: Domain List (24) | |
packet[i++] = (DHCPV6_DOMAIN_LIST >> 8) & 0xFF; | |
packet[i++] = DHCPV6_DOMAIN_LIST & 0xFF; | |
packet[i++] = 0x00; // Length (0 for now, will be filled later) | |
packet[i++] = 0x00; | |
packet[i++] = (SIP_SERVER_A >> 8) & 0xFF; | |
packet[i++] = SIP_SERVER_A & 0xFF; | |
packet[i++] = 0x00; // Length (0 for now, will be filled later) | |
packet[i++] = 0x00; | |
// Option: Domain List (24) | |
packet[i++] = (SIP_SERVER_D >> 8) & 0xFF; | |
packet[i++] = SIP_SERVER_D & 0xFF; | |
packet[i++] = 0x00; // Length (0 for now, will be filled later) | |
packet[i++] = 0x00; | |
#endif | |
packet[i++] = (OPTION_REQUEST_OPTION >> 8) & 0xFF; | |
packet[i++] = OPTION_REQUEST_OPTION & 0xFF; | |
packet[i++] = 0; | |
packet[i++] = 8; | |
packet[i++] = (DHCPV6_DNS_SERVERS >> 8) & 0xFF; | |
packet[i++] = DHCPV6_DNS_SERVERS & 0xFF; | |
packet[i++] = (DHCPV6_DOMAIN_LIST >> 8) & 0xFF; | |
packet[i++] = DHCPV6_DOMAIN_LIST & 0xFF; | |
packet[i++] = (SIP_SERVER_D >> 8) & 0xFF; | |
packet[i++] = SIP_SERVER_D & 0xFF; | |
packet[i++] = (SIP_SERVER_A >> 8) & 0xFF; | |
packet[i++] = SIP_SERVER_A & 0xFF; | |
// Option: End (255) | |
packet[i++] = 0xFF; | |
return i; | |
} | |
// Function to get the interface index by name | |
int get_interface_index(const char *ifname) { | |
struct ifaddrs *ifaddr, *ifa; | |
int ifindex = -1; | |
if (getifaddrs(&ifaddr) == -1) { | |
perror("getifaddrs"); | |
exit(EXIT_FAILURE); | |
} | |
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { | |
if (ifa->ifa_addr == NULL) | |
continue; | |
if (strcmp(ifa->ifa_name, ifname) == 0) { | |
ifindex = if_nametoindex(ifa->ifa_name); | |
break; | |
} | |
} | |
freeifaddrs(ifaddr); | |
return ifindex; | |
} | |
// Function to send the DHCPv6 Information Request packet | |
void send_dhcpv6_info_request(const char *ifname) { | |
int sockfd; | |
struct sockaddr_in6 server_addr; | |
unsigned char packet[1024]; | |
int packet_len; | |
int ifindex; | |
// Create a raw socket | |
sockfd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); | |
if (sockfd < 0) { | |
perror("socket"); | |
exit(EXIT_FAILURE); | |
} | |
// Set the interface index for sending multicast packets | |
ifindex = get_interface_index(ifname); | |
if (ifindex == -1) { | |
perror("get_interface_index"); | |
close(sockfd); | |
exit(EXIT_FAILURE); | |
} | |
if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)) < 0) { | |
perror("setsockopt"); | |
close(sockfd); | |
exit(EXIT_FAILURE); | |
} | |
struct sockaddr_in6 serv_addr; | |
socklen_t addrlen = sizeof(serv_addr); | |
// Prepare the sockaddr_in6 structure | |
memset(&serv_addr, 0, sizeof(serv_addr)); | |
serv_addr.sin6_family = AF_INET6; | |
serv_addr.sin6_addr = in6addr_any; // Bind to all available IPv6 addresses | |
serv_addr.sin6_port = htons(546); // DHCPv6 client port | |
// Bind the socket to the DHCPv6 client port | |
if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { | |
perror("Bind failed"); | |
close(sockfd); | |
exit(EXIT_FAILURE); | |
} | |
// Set up the server address | |
memset(&server_addr, 0, sizeof(server_addr)); | |
server_addr.sin6_family = AF_INET6; | |
server_addr.sin6_port = htons(DHCPV6_SERVER_PORT); | |
inet_pton(AF_INET6, DHCPV6_MULTICAST_GROUP, &server_addr.sin6_addr); | |
// Create the DHCPv6 Information Request packet | |
packet_len = create_dhcpv6_info_request(packet); | |
// Send the packet | |
if (sendto(sockfd, packet, packet_len, 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { | |
perror("sendto"); | |
close(sockfd); | |
exit(EXIT_FAILURE); | |
} | |
printf("DHCPv6 Information Request sent successfully on interface %s.\n", ifname); | |
// Close the socket | |
close(sockfd); | |
} | |
int main(int argc, char *argv[]) { | |
if (argc != 2) { | |
fprintf(stderr, "Usage: %s <interface>\n", argv[0]); | |
exit(EXIT_FAILURE); | |
} | |
const char *ifname = argv[1]; | |
send_dhcpv6_info_request(ifname); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment