linux/arch/um/drivers/umcast_kern.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * user-mode-linux networking multicast transport
   4 * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org>
   5 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
   6 *
   7 * based on the existing uml-networking code, which is
   8 * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
   9 * James Leu (jleu@mindspring.net).
  10 * Copyright (C) 2001 by various other people who didn't put their name here.
  11 *
  12 */
  13
  14#include <linux/init.h>
  15#include <linux/netdevice.h>
  16#include "umcast.h"
  17#include <net_kern.h>
  18
  19struct umcast_init {
  20        char *addr;
  21        int lport;
  22        int rport;
  23        int ttl;
  24        bool unicast;
  25};
  26
  27static void umcast_init(struct net_device *dev, void *data)
  28{
  29        struct uml_net_private *pri;
  30        struct umcast_data *dpri;
  31        struct umcast_init *init = data;
  32
  33        pri = netdev_priv(dev);
  34        dpri = (struct umcast_data *) pri->user;
  35        dpri->addr = init->addr;
  36        dpri->lport = init->lport;
  37        dpri->rport = init->rport;
  38        dpri->unicast = init->unicast;
  39        dpri->ttl = init->ttl;
  40        dpri->dev = dev;
  41
  42        if (dpri->unicast) {
  43                printk(KERN_INFO "ucast backend address: %s:%u listen port: "
  44                       "%u\n", dpri->addr, dpri->rport, dpri->lport);
  45        } else {
  46                printk(KERN_INFO "mcast backend multicast address: %s:%u, "
  47                       "TTL:%u\n", dpri->addr, dpri->lport, dpri->ttl);
  48        }
  49}
  50
  51static int umcast_read(int fd, struct sk_buff *skb, struct uml_net_private *lp)
  52{
  53        return net_recvfrom(fd, skb_mac_header(skb),
  54                            skb->dev->mtu + ETH_HEADER_OTHER);
  55}
  56
  57static int umcast_write(int fd, struct sk_buff *skb, struct uml_net_private *lp)
  58{
  59        return umcast_user_write(fd, skb->data, skb->len,
  60                                (struct umcast_data *) &lp->user);
  61}
  62
  63static const struct net_kern_info umcast_kern_info = {
  64        .init                   = umcast_init,
  65        .protocol               = eth_protocol,
  66        .read                   = umcast_read,
  67        .write                  = umcast_write,
  68};
  69
  70static int mcast_setup(char *str, char **mac_out, void *data)
  71{
  72        struct umcast_init *init = data;
  73        char *port_str = NULL, *ttl_str = NULL, *remain;
  74        char *last;
  75
  76        *init = ((struct umcast_init)
  77                { .addr = "239.192.168.1",
  78                  .lport        = 1102,
  79                  .ttl  = 1 });
  80
  81        remain = split_if_spec(str, mac_out, &init->addr, &port_str, &ttl_str,
  82                               NULL);
  83        if (remain != NULL) {
  84                printk(KERN_ERR "mcast_setup - Extra garbage on "
  85                       "specification : '%s'\n", remain);
  86                return 0;
  87        }
  88
  89        if (port_str != NULL) {
  90                init->lport = simple_strtoul(port_str, &last, 10);
  91                if ((*last != '\0') || (last == port_str)) {
  92                        printk(KERN_ERR "mcast_setup - Bad port : '%s'\n",
  93                               port_str);
  94                        return 0;
  95                }
  96        }
  97
  98        if (ttl_str != NULL) {
  99                init->ttl = simple_strtoul(ttl_str, &last, 10);
 100                if ((*last != '\0') || (last == ttl_str)) {
 101                        printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n",
 102                               ttl_str);
 103                        return 0;
 104                }
 105        }
 106
 107        init->unicast = false;
 108        init->rport = init->lport;
 109
 110        printk(KERN_INFO "Configured mcast device: %s:%u-%u\n", init->addr,
 111               init->lport, init->ttl);
 112
 113        return 1;
 114}
 115
 116static int ucast_setup(char *str, char **mac_out, void *data)
 117{
 118        struct umcast_init *init = data;
 119        char *lport_str = NULL, *rport_str = NULL, *remain;
 120        char *last;
 121
 122        *init = ((struct umcast_init)
 123                { .addr         = "",
 124                  .lport        = 1102,
 125                  .rport        = 1102 });
 126
 127        remain = split_if_spec(str, mac_out, &init->addr,
 128                               &lport_str, &rport_str, NULL);
 129        if (remain != NULL) {
 130                printk(KERN_ERR "ucast_setup - Extra garbage on "
 131                       "specification : '%s'\n", remain);
 132                return 0;
 133        }
 134
 135        if (lport_str != NULL) {
 136                init->lport = simple_strtoul(lport_str, &last, 10);
 137                if ((*last != '\0') || (last == lport_str)) {
 138                        printk(KERN_ERR "ucast_setup - Bad listen port : "
 139                               "'%s'\n", lport_str);
 140                        return 0;
 141                }
 142        }
 143
 144        if (rport_str != NULL) {
 145                init->rport = simple_strtoul(rport_str, &last, 10);
 146                if ((*last != '\0') || (last == rport_str)) {
 147                        printk(KERN_ERR "ucast_setup - Bad remote port : "
 148                               "'%s'\n", rport_str);
 149                        return 0;
 150                }
 151        }
 152
 153        init->unicast = true;
 154
 155        printk(KERN_INFO "Configured ucast device: :%u -> %s:%u\n",
 156               init->lport, init->addr, init->rport);
 157
 158        return 1;
 159}
 160
 161static struct transport mcast_transport = {
 162        .list   = LIST_HEAD_INIT(mcast_transport.list),
 163        .name   = "mcast",
 164        .setup  = mcast_setup,
 165        .user   = &umcast_user_info,
 166        .kern   = &umcast_kern_info,
 167        .private_size   = sizeof(struct umcast_data),
 168        .setup_size     = sizeof(struct umcast_init),
 169};
 170
 171static struct transport ucast_transport = {
 172        .list   = LIST_HEAD_INIT(ucast_transport.list),
 173        .name   = "ucast",
 174        .setup  = ucast_setup,
 175        .user   = &umcast_user_info,
 176        .kern   = &umcast_kern_info,
 177        .private_size   = sizeof(struct umcast_data),
 178        .setup_size     = sizeof(struct umcast_init),
 179};
 180
 181static int register_umcast(void)
 182{
 183        register_transport(&mcast_transport);
 184        register_transport(&ucast_transport);
 185        return 0;
 186}
 187
 188late_initcall(register_umcast);
 189