/*
 * DF-3462: one-shot UDP sender. Creates a socket and issues a single
 * sendto() WITHOUT connect(), so the udp_output/ip_output/pfil(OUT)
 * path runs on the cpu where the socket was created (inp_initport()
 * -> netisr_cpuport(mycpuid) of the creator thread).
 *
 * usage: udp1shot <dstip> <dstport> [payload]
 */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

int
main(int argc, char **argv)
{
	struct sockaddr_in dst;
	int s, n, err;
	const char *msg = "df3462";

	if (argc < 3) {
		fprintf(stderr, "usage: %s <dstip> <dstport> [payload]\n",
		    argv[0]);
		return (2);
	}
	memset(&dst, 0, sizeof(dst));
	dst.sin_family = AF_INET;
	dst.sin_port = htons((u_short)atoi(argv[2]));
	if (inet_pton(AF_INET, argv[1], &dst.sin_addr) != 1) {
		perror("inet_pton");
		return (2);
	}
	if (argc > 3)
		msg = argv[3];

	s = socket(AF_INET, SOCK_DGRAM, 0);
	if (s < 0) {
		perror("socket");
		return (2);
	}
	if (argc > 4) {
		struct sockaddr_in src;

		memset(&src, 0, sizeof(src));
		src.sin_family = AF_INET;
		src.sin_port = htons((u_short)atoi(argv[4]));
		if (argc > 5)
			inet_pton(AF_INET, argv[5], &src.sin_addr);
		if (bind(s, (struct sockaddr *)&src, sizeof(src)) < 0) {
			perror("bind");
			return (2);
		}
	}
	n = sendto(s, msg, strlen(msg), 0,
	    (struct sockaddr *)&dst, sizeof(dst));
	err = errno;
	close(s);
	if (n < 0) {
		printf("sendto failed: %s\n", strerror(err));
		return (1);
	}
	printf("sent %d bytes\n", n);
	return (0);
}
