/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk) */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include ax25_dev *ax25_dev_list; DEFINE_SPINLOCK(ax25_dev_lock); ax25_dev *ax25_addr_ax25dev(ax25_address *addr) { ax25_dev *ax25_dev, *res = NULL; spin_lock_bh(&ax25_dev_lock); for (ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next) if (ax25cmp(addr, (ax25_address *)ax25_dev->dev->dev_addr) == 0) { res = ax25_dev; } spin_unlock_bh(&ax25_dev_lock); return res; } /* * This is called when an interface is brought up. These are * reasonable defaults. */ void ax25_dev_device_up(struct net_device *dev) { ax25_dev *ax25_dev; if ((ax25_dev = kmalloc(sizeof(*ax25_dev), GFP_ATOMIC)) == NULL) { printk(KERN_ERR "AX.25: ax25_dev_device_up - out of memory\n"); return; } ax25_unregister_sysctl(); memset(ax25_dev, 0x00, sizeof(*ax25_dev)); dev->ax25_ptr = ax25_dev; ax25_dev->dev = dev; dev_hold(dev); ax25_dev->forward = NULL; ax25_dev->values[AX25_VALUES_IPDEFMODE] = AX25_DEF_IPDEFMODE; ax25_dev->values[AX25_VALUES_AXDEFMODE] = AX25_DEF_AXDEFMODE; ax25_dev->values[AX25_VALUES_BACKOFF] = AX25_DEF_BACKOFF; ax25_dev->values[AX25_VALUES_CONMODE] = AX25_DEF_CONMODE; ax25_dev->values[AX25_VALUES_WINDOW] = AX25_DEF_WINDOW; ax25_dev->values[AX25_VALUES_EWINDOW] = AX25_DEF_EWINDOW; ax25_dev->values[AX25_VALUES_T1] = AX25_DEF_T1; ax25_dev->values[AX25_VALUES_T2] = AX25_DEF_T2; ax25_dev->values[AX25_VALUES_T3] = AX25_DEF_T3; ax25_dev->values[AX25_VALUES_IDLE] = AX25_DEF_IDLE; ax25_dev->values[AX25_VALUES_N2] = AX25_DEF_N2; ax25_dev->values[AX25_VALUES_PACLEN] = AX25_DEF_PACLEN; ax25_dev->values[AX25_VALUES_PROTOCOL] = AX25_DEF_PROTOCOL; ax25_dev->values[AX25_VALUES_DS_TIMEOUT]= AX25_DEF_DS_TIMEOUT; #if defined(CONFIG_AX25_DAMA_SLAVE) || defined(CONFIG_AX25_DAMA_MASTER) init_timer(&ax25_dev->dama.slave_timer); #endif spin_lock_bh(&ax25_dev_lock); ax25_dev->next = ax25_dev_list; ax25_dev_list = ax25_dev; spin_unlock_bh(&ax25_dev_lock); ax25_register_sysctl(); } void ax25_dev_device_down(struct net_device *dev) { ax25_dev *s, *ax25_dev; if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL) return; ax25_unregister_sysctl(); spin_lock_bh(&ax25_dev_lock); #ifdef CONFIG_AX25_DAMA_SLAVE ax25_ds_del_timer(ax25_dev); #endif /* * Remove any packet forwarding that points to this device. */ for (s = ax25_dev_list; s != NULL; s = s->next) if (s->forward == dev) s->forward = NULL; if ((s = ax25_dev_list) == ax25_dev) { ax25_dev_list = s->next; spin_unlock_bh(&ax25_dev_lock); dev_put(dev); kfree(ax25_dev); ax25_register_sysctl(); return; } while (s != NULL && s->next != NULL) { if (s->next == ax25_dev) { s->next = ax25_dev->next; spin_unlock_bh(&ax25_dev_lock); dev_put(dev); kfree(ax25_dev); ax25_register_sysctl(); return; } s = s->next; } spin_unlock_bh(&ax25_dev_lock); dev->ax25_ptr = NULL; ax25_register_sysctl(); } int ax25_fwd_ioctl(unsigned int cmd, struct ax25_fwd_struct *fwd) { ax25_dev *ax25_dev, *fwd_dev; if ((ax25_dev = ax25_addr_ax25dev(&fwd->port_from)) == NULL) return -EINVAL; switch (cmd) { case SIOCAX25ADDFWD: if ((fwd_dev = ax25_addr_ax25dev(&fwd->port_to)) == NULL) return -EINVAL; if (ax25_dev->forward != NULL) return -EINVAL; ax25_dev->forward = fwd_dev->dev; break; case SIOCAX25DELFWD: if (ax25_dev->forward == NULL) return -EINVAL; ax25_dev->forward = NULL; break; default: return -EINVAL; } return 0; } struct net_device *ax25_fwd_dev(struct net_device *dev) { ax25_dev *ax25_dev; if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL) return dev; if (ax25_dev->forward == NULL) return dev; return ax25_dev->forward; } /* * Free all memory associated with device structures. */ void __exit ax25_dev_free(void) { ax25_dev *s, *ax25_dev; spin_lock_bh(&ax25_dev_lock); ax25_dev = ax25_dev_list; while (ax25_dev != NULL) { s = ax25_dev; dev_put(ax25_dev->dev); ax25_dev = ax25_dev->next; kfree(s); } ax25_dev_list = NULL; spin_unlock_bh(&ax25_dev_lock); } #n34'>34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
/* Framework for new probes using the runtime */
/* this example shows both kprobes and jprobes although you */
/* likely will only want one. */

/* define this if you don't want to use relayfs.  Normally */
/* you want relayfs, unless you need a realtime stream of data */

#define STP_NETLINK_ONLY

/* How many strings to allocate. see strings.c. Default is 0. */
#define STP_NUM_STRINGS 1

/* maximum size for a string. default is 2048 */
#define STP_STRING_SIZE 2048

/* size of strings saved in maps */
#define MAP_STRING_LENGTH 256

/* width of histograms. Default 50 */
#define HIST_WIDTH 50

/* always include this.  Put all non-map defines above it. */
#include "runtime.h"

/* These are the possible values a map can have. */
/* Comment out unused ones. Comment out all if you don't need maps. */
#define NEED_INT64_VALS
#define NEED_STRING_VALS
#define NEED_STAT_VALS

/* now for each set of keys, define the key type and include map-keys.c */
/* This define a single key of int64, for example map1[2048] */
#define KEY1_TYPE INT64
#include "map-keys.c"

/* This generates code to handle keys of int64,string, for example */
/* map2[1000,"Cobalt"] */
#define KEY1_TYPE INT64
#define KEY2_TYPE STRING
#include "map-keys.c"

/* After defining all your key combinations, include map.c */
#include "map.c"

/* include if you use lists */
#include "list.c"

/* include if you use copy_from_user functions */
#include "copy.c"

/* include if you use the _stp_register_probe functions */
#include "probes.c"

MODULE_DESCRIPTION("SystemTap probe: myname");
MODULE_AUTHOR("Me <myname@nowhere.com>");

/* here is an example jprobe instrumentation function. */
/* jprobes require a prototype matching the probed function. */

static int inst_meminfo_read_proc(char *page, char **start, off_t off,
                                 int count, int *eof, void *data)
{
  _stp_print("Now in meminfo\n");
  _stp_stack_printj();
  _stp_ustack_print();
  jprobe_return();
  return 0;
}

/* here is an example kprobe. kprobes always take the same arguments */
static int inst_uptime_read_proc(struct kprobe *p, struct pt_regs *regs)
{
  _stp_stack_print(regs);
  _stp_ustack_print();
  return 0;
}

/* put jprobes here */
static struct jprobe jp[] = {
  {
    .kp.addr = (kprobe_opcode_t *)"meminfo_read_proc",
    .entry = (kprobe_opcode_t *) inst_meminfo_read_proc
  },
};

/* put kprobes here */
static struct kprobe kp[] = {
  {
    .addr = "uptime_read_proc",
    .pre_handler = inst_uptime_read_proc,
  }
};

#define NUM_JPROBES (sizeof(jp)/sizeof(struct jprobe))
#define NUM_KPROBES (sizeof(kp)/sizeof(struct kprobe))

/* called when the module loads. */
int probe_start(void)
{
  /* initialize any data or variables */


  /* register any jprobes */
  int ret = _stp_register_jprobes (jp, NUM_JPROBES);

  /* Register any kprobes and jprobes. */
  /* You probably only have one type */
  if (ret >= 0)
    if ((ret = _stp_register_kprobes (kp, NUM_KPROBES)) < 0)
      _stp_unregister_jprobes (jp, NUM_JPROBES);

  return ret;
}


void probe_exit (void)
{
  /* unregister the probes */
  _stp_unregister_jprobes (jp, NUM_JPROBES);
  _stp_unregister_kprobes (kp, NUM_KPROBES);

  /* print out any colledted data, etc */
  _stp_printf ("whatever I want to say\n");
  _stp_print_flush();
}