For obtaining the MTU in your interface, not for Path MTU discovery, you have struct ifreq. One of its fields is ifr_mtu and this field will provide you the MTU. You read this field with ioctl, SIOCGIFMTU for the proper interface.
(http://man7.org/linux/man-pages/man7/netdevice.7.html)
struct ifreq {
char ifr_name[IFNAMSIZ]; /* Interface name */
union {
struct sockaddr ifr_addr;
struct sockaddr ifr_dstaddr;
struct sockaddr ifr_broadaddr;
struct sockaddr ifr_netmask;
struct sockaddr ifr_hwaddr;
short ifr_flags;
int ifr_ifindex;
int ifr_metric;
int ifr_mtu;
struct ifmap ifr_map;
char ifr_slave[IFNAMSIZ];
char ifr_newname[IFNAMSIZ];
char *ifr_data;
};
};
Example:
#include <sys/socket.h>
#include <sys/types.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
int main(void)
{
int sock;
char *name = "enp0s3";
struct ifreq ifr;
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
printf("Creating socket: %d\n", errno);
exit(-1);
}
ifr.ifr_addr.sa_family = AF_INET;
strcpy(ifr.ifr_name, name);
if (ioctl(sock, SIOCGIFMTU, (caddr_t)&ifr) < 0) {
printf("Error ioctl: %d\n", errno);
exit(-2);
}
printf("MTU is %d.\n", ifr.ifr_mtu);
close(sock);
return 0;
}
Today, in general you can trust an MTU of 1,500 in the Internet unless you use specific connection technologies like Bluetooth or Zigbee. You can use Path MTU Discovery and implement your UDP-based protocol with an ACK to check the other side has received the message. Now, implementing an ACK and features of connection-oriented protocol is not the same as using TCP. If you can do everything with UDP it is lighter than TCP.
Edit:
For using Path MTU Discovery, you can also use getsockopt with option IP_PMTUDISC_DO:
IP_MTU_DISCOVER (since Linux 2.2)
Set or receive the Path MTU Discovery setting for a socket.
When enabled, Linux will perform Path MTU Discovery as defined
in RFC 1191 on SOCK_STREAM sockets. For non-SOCK_STREAM
sockets, IP_PMTUDISC_DO forces the don't-fragment flag to be
set on all outgoing packets. It is the user's responsibility
to packetize the data in MTU-sized chunks and to do the
retransmits if necessary. The kernel will reject (with
EMSGSIZE) datagrams that are bigger than the known path MTU.
IP_PMTUDISC_WANT will fragment a datagram if needed according
to the path MTU, or will set the don't-fragment flag
otherwise.
See more here: http://man7.org/linux/man-pages/man7/ip.7.html