Getting the value of bitrate from a wireless device driver. - linux

I'm writing a kernel module that needs to read the value of bitrate from this union:
union iwreq_data
{==
.......
struct iw_param bitrate; /* default bit rate */
....
}
This code is form wireless.h Does anyone know how I can access it's value?
(I'm using linux kernel 2.6.35)

There's no way to do that, unfortunately ...
taking a closer look at the iw_param struct we find
struct iw_param
{
__s32 value; /* The value of the parameter itself */
__u8 fixed; /* Hardware should not use auto select */
__u8 disabled; /* Disable the feature */
__u16 flags; /* Various specifc flags (if any) */
};
now, here's what the code looks like in wireless.h
union iwreq_data
{
/* Config - generic */
char name[IFNAMSIZ];
/* Name : used to verify the presence of wireless extensions.
* Name of the protocol/provider... */
struct iw_point essid; /* Extended network name */
struct iw_param nwid; /* network id (or domain - the cell) */
struct iw_freq freq; /* frequency or channel :
* 0-1000 = channel
* > 1000 = frequency in Hz */
struct iw_param sens; /* signal level threshold */
struct iw_param bitrate; /* default bit rate */
struct iw_param txpower; /* default transmit power */
struct iw_param rts; /* RTS threshold threshold */
struct iw_param frag; /* Fragmentation threshold */
__u32 mode; /* Operation mode */
struct iw_param retry; /* Retry limits & lifetime */
struct iw_point encoding; /* Encoding stuff : tokens */
struct iw_param power; /* PM duration/timeout */
struct iw_quality qual; /* Quality part of statistics */
struct sockaddr ap_addr; /* Access point address */
struct sockaddr addr; /* Destination address (hw/mac) */
struct iw_param param; /* Other small parameters */
struct iw_point data; /* Other large parameters */
};
I cannot think of a way to access it other than bitrate->value

Related

Where the structure "struct page" is stored on the linux kernel?

I learned that linux kernel manages the memory and the unit for allocate/deallocate the memory is 4KB, which is the page size. And I know that this pages are handled by struct page.
I got a actual code here.
struct page {
unsigned long flags; /* Atomic flags, some possibly
* updated asynchronously */
/*
* Five words (20/40 bytes) are available in this union.
* WARNING: bit 0 of the first word is used for PageTail(). That
* means the other users of this union MUST NOT use the bit to
* avoid collision and false-positive PageTail().
*/
union {
struct { /* Page cache and anonymous pages */
/**
* #lru: Pageout list, eg. active_list protected by
* pgdat->lru_lock. Sometimes used as a generic list
* by the page owner.
*/
struct list_head lru;
/* See page-flags.h for PAGE_MAPPING_FLAGS */
struct address_space *mapping;
pgoff_t index; /* Our offset within mapping. */
/**
* #private: Mapping-private opaque data.
* Usually used for buffer_heads if PagePrivate.
* Used for swp_entry_t if PageSwapCache.
* Indicates order in the buddy system if PageBuddy.
*/
unsigned long private;
};
struct { /* page_pool used by netstack */
/**
* #dma_addr: might require a 64-bit value even on
* 32-bit architectures.
*/
dma_addr_t dma_addr;
};
struct { /* slab, slob and slub */
union {
struct list_head slab_list;
struct { /* Partial pages */
struct page *next;
#ifdef CONFIG_64BIT
int pages; /* Nr of pages left */
int pobjects; /* Approximate count */
#else
short int pages;
short int pobjects;
#endif
};
};
struct kmem_cache *slab_cache; /* not slob */
/* Double-word boundary */
void *freelist; /* first free object */
union {
void *s_mem; /* slab: first object */
unsigned long counters; /* SLUB */
struct { /* SLUB */
unsigned inuse:16;
unsigned objects:15;
unsigned frozen:1;
};
};
};
struct { /* Tail pages of compound page */
unsigned long compound_head; /* Bit zero is set */
/* First tail page only */
unsigned char compound_dtor;
unsigned char compound_order;
atomic_t compound_mapcount;
};
struct { /* Second tail page of compound page */
unsigned long _compound_pad_1; /* compound_head */
atomic_t hpage_pinned_refcount;
/* For both global and memcg */
struct list_head deferred_list;
};
struct { /* Page table pages */
unsigned long _pt_pad_1; /* compound_head */
pgtable_t pmd_huge_pte; /* protected by page->ptl */
unsigned long _pt_pad_2; /* mapping */
union {
struct mm_struct *pt_mm; /* x86 pgds only */
atomic_t pt_frag_refcount; /* powerpc */
};
#if ALLOC_SPLIT_PTLOCKS
spinlock_t *ptl;
#else
spinlock_t ptl;
#endif
};
struct { /* ZONE_DEVICE pages */
/** #pgmap: Points to the hosting device page map. */
struct dev_pagemap *pgmap;
void *zone_device_data;
/*
* ZONE_DEVICE private pages are counted as being
* mapped so the next 3 words hold the mapping, index,
* and private fields from the source anonymous or
* page cache page while the page is migrated to device
* private memory.
* ZONE_DEVICE MEMORY_DEVICE_FS_DAX pages also
* use the mapping, index, and private fields when
* pmem backed DAX files are mapped.
*/
};
/** #rcu_head: You can use this to free a page by RCU. */
struct rcu_head rcu_head;
};
union { /* This union is 4 bytes in size. */
/*
* If the page can be mapped to userspace, encodes the number
* of times this page is referenced by a page table.
*/
atomic_t _mapcount;
/*
* If the page is neither PageSlab nor mappable to userspace,
* the value stored here may help determine what this page
* is used for. See page-flags.h for a list of page types
* which are currently stored here.
*/
unsigned int page_type;
unsigned int active; /* SLAB */
int units; /* SLOB */
};
/* Usage count. *DO NOT USE DIRECTLY*. See page_ref.h */
atomic_t _refcount;
#ifdef CONFIG_MEMCG
struct mem_cgroup *mem_cgroup;
#endif
/*
* On machines where all RAM is mapped into kernel address space,
* we can simply calculate the virtual address. On machines with
* highmem some memory is mapped into kernel virtual memory
* dynamically, so we need a place to store that address.
* Note that this field could be 16 bits on x86 ... ;)
*
* Architectures with slow multiplication can define
* WANT_PAGE_VIRTUAL in asm/page.h
*/
#if defined(WANT_PAGE_VIRTUAL)
void *virtual; /* Kernel virtual address (NULL if
not kmapped, ie. highmem) */
#endif /* WANT_PAGE_VIRTUAL */
#ifdef LAST_CPUPID_NOT_IN_PAGE_FLAGS
int _last_cpupid;
#endif
} _struct_page_alignment;
And I have no idea where the linux kernel stores this huge(?) structure.
There are a lot of pages handled in the linux kernel and that means that we have a lot of this struct page structures. Where can it be stored on the memory?
Also I have no idea what the union up there is up for.
First, there are several memory models like FMM, SMP, and NUMA. The knowledge about virtual memory, page and page tables, sturct of kernel and user space memory may not write here because there are too much more than the limitation of the answer's length and I think you can learn it from any books.
Let's use NUMA as an example. In NUMA, every CPU will have a node : struct pglist_data *node_data, and this struct has many Zones like ZONE_DMA, ZONE_DMA32, ZONE_NORMAL, ZONE_HIGHMEM, ZONE_MOVALBE, every Zone has many struct free_area, and this struct includes a list of struct page.
Why we need to use page? It is because our physical memory is limit, so we create virtual memory. And then we need a mechanism to load virtual memory to physical memory to run the task(process or thread). So we use page as the meta entry, and use some models like NUMA to control those pages and page tables.
When we need to allocate some memory, we will use buddy system and slab/slub allocator to allocate memory pages and add them to a zone that can use. When the physical memory loads too much pages, it will use get_page_from_freelist() or kswapd to swap some out.
Auctally, memory and addresses space is a essential part of Linux kernel. I suggest you to read some books like CSAPP to get a relatively deep understand of OS, and then reading Linux kernel source codes to dive into them.
I have the same question as you recently.
Where is the struct page in Linux kernel?
And I think I can give you some helpful informations. Every node stores pages into pg_data_t's node_mem_map, and there is a global variable mem_map, which is pointing to Node 0's page array.
You can find more details from Professional Linux Kernel Architecture. In chapter 3, the section is "Creating Data Structures for Each Node".
If you want to know exact place where it is stored, this article might give you the answer.
It says that they are "usually stored at the beginning of ZONE_NORMAL".

In Linux is there a standard call to resolve a pathname to an inode?

Making a kernel module to link an inode to a directory. Beginner so on the learning curve. The plan is to resolve the directory to an inode, find its superblock and then get the inode from the file with iget_locked, finally link that inode into the dentry of the target directory and increment its link count.
syscall stat will take a pathname as input and dump a stat struct.
int stat(const char *pathname, struct stat *statbuf);
The inode to the file can be find as a member of the struct:
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* Inode number */
mode_t st_mode; /* File type and mode */
nlink_t st_nlink; /* Number of hard links */
uid_t st_uid; /* User ID of owner */
gid_t st_gid; /* Group ID of owner */
dev_t st_rdev; /* Device ID (if special file) */
off_t st_size; /* Total size, in bytes */
blksize_t st_blksize; /* Block size for filesystem I/O */
blkcnt_t st_blocks; /* Number of 512B blocks allocated */
/* Since Linux 2.6, the kernel supports nanosecond
precision for the following timestamp fields.
For the details before Linux 2.6, see NOTES. */
struct timespec st_atim; /* Time of last access */
struct timespec st_mtim; /* Time of last modification */
struct timespec st_ctim; /* Time of last status change */
#define st_atime st_atim.tv_sec /* Backward compatibility */
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};
Referring to manpage stat(2). Hope this answers your question.

Best way to calculate the free space using statvfs structure?

whether we have to use
f_bfree × f_frsize
or
f_bfree × f_bsize
to calculate the free disk space in a file system
struct statvfs {
unsigned long f_bsize; /* file system block size */
unsigned long f_frsize; /* fragment size */
fsblkcnt_t f_blocks; /* size of fs in f_frsize units */
fsblkcnt_t f_bfree; /* # free blocks */
fsblkcnt_t f_bavail; /* # free blocks for unprivileged users */
fsfilcnt_t f_files; /* # inodes */
fsfilcnt_t f_ffree; /* # free inodes */
fsfilcnt_t f_favail; /* # free inodes for unprivileged users */
unsigned long f_fsid; /* file system ID */
unsigned long f_flag; /* mount flags */
unsigned long f_namemax; /* maximum filename length */
};

DOS: how to get current country code or code page in Turbo C

How to get some locale-specific information where the country can be detected? E.g. current country code, keyboard layout or code page in Turbo C in DOS environment?
If that is not possible with Turbo C library functions, some BIOS calls could do that (INT 21)?.
KEYB program is able to show e.g. keyboard layout. That would be more than enough for my purposes:
https://www.dosbox.com/wiki/KEYB
Use INT 21h, AX=6501h. Here's code for Turbo C:
#include <dos.h>
#include <stdio.h>
struct country_info_buffer
{
unsigned char info_id;
unsigned short buffer_size;
unsigned short country_id;
unsigned short code_page;
struct COUNTRY country_info;
};
int main()
{
/* Registers for INT21 call */
union REGS regs;
struct SREGS sregs;
/* Output buffer */
struct country_info_buffer info;
/* Get current value of segment registers */
segread(&sregs);
/* Get extended country information / general internationalization info */
regs.x.ax = 0x6501;
/* Global code page */
regs.x.bx = 0xFFFF;
/* Current country */
regs.x.dx = 0xFFFF;
/* Size of output buffer */
regs.x.cx = sizeof(info);
/* Pointer to output buffer goes to ES:DI */
sregs.es = FP_SEG(&info);
regs.x.di = FP_OFF(&info);
/* Call int21 */
intdosx(&regs, &regs, &sregs);
if (regs.x.cflag)
{
printf("Call failed, ax=%d\n", regs.x.ax);
return 1;
}
printf("Country code: %d, Code page: %d\n", info.country_id, info.code_page);
return 0;
}
Btw. Ralf Brown's Interrupt List is great resource for DOS system calls. Too bad it stopped being maintained even before DOS ran out of favors, so some "newest" stuff isn't described there.

Changing mac-address of packets with winpcap

I am an absolute beginner with winpcap and c++. I want to read dump files, change the MAC-address(es) of some packets and delete the other packets. So in the end, my file is only supposed to contain the changed packets (same file as before, only without the 'unimportant' packtes).
I use Qt Creator, mingw, c++ and winpcap (of course).
What works so far: Reading from the file, displaying the mac/ip/whatever I want.
What does not work: Editing the packets.
I use some structs to read the data out of my packet:
struct pcap_hdr_s {
public:
uint32_t magic_number; /* magic number */
uint16_t version_major; /* major version number */
uint16_t version_minor; /* minor version number */
int32_t thiszone; /* GMT to local correction */
uint32_t sigfigs; /* accuracy of timestamps */
uint32_t snaplen; /* max length of captured packets, in octets */
uint32_t network; /* data link type */
};
struct pcaprec_hdr_s {
public:
uint32_t ts_sec; /* timestamp seconds */
uint32_t ts_usec; /* timestamp microseconds */
uint32_t incl_len; /* number of octets of packet saved in file */
uint32_t orig_len; /* actual length of packet */
} ;
struct ip_address{
public:
u_char byte1;
u_char byte2;
u_char byte3;
u_char byte4;
};
struct mac_adress{
public:
u_char mac1;
u_char mac2;
u_char mac3;
u_char mac4;
u_char mac5;
u_char mac6;
};
/*Ethernet header*/
struct eth_header{
public:
mac_adress dst_mac;
mac_adress src_mac;
uint16_t type;
};
/* IPv4 header */
struct ip_header{
public:
u_char ver_ihl; // Version (4 bits) + Internet header length (4 bits)
u_char tos; // Type of service
u_short tlen; // Total length
u_short identification; // Identification
u_short flags_fo; // Flags (3 bits) + Fragment offset (13 bits)
u_char ttl; // Time to live
u_char proto; // Protocol
u_short crc; // Header checksum
ip_address* saddr; // Source address
ip_address* daddr; // Destination address
//u_int op_pad; // Option + Padding --> optional
};
/* UDP header*/
struct udp_header{
public:
u_short sport; // Source port
u_short dport; // Destination port
u_short len; // Datagram length
u_short crc; // Checksum
};
This is my code so far for editing the packets:
void changeMAC(QString wantedMac, QString file){
const u_char *pkt_data;
struct pcap_pkthdr *header;
pcap_t *pd;
pcap_dumper_t *pdumper;
eth_header *ethHeader;
ip_header *ipHeader;
int res = 0;
QString check;
pd = pcap_open_dead(DLT_EN10MB, 65535);
/*output file = input file*/
pdumper = pcap_dump_open(pd, qPrintable(file));
while((res = pcap_next_ex(pd, &header, &pkt_data)) >= 0){//iterate through the packets in the file
ipHeader = (ip_header *)(pkt_data + 14);
if(ipHeader->proto == 17){ //I only have a look at udp
ethHeader = (eth_header *)(pkt_data); //check if this is the MAC I want to cahnge
check.clear();
check.append(ethHeader->dst_mac.mac1);
check.append(ethHeader->dst_mac.mac2);
check.append(ethHeader->dst_mac.mac3);
check.append(ethHeader->dst_mac.mac4);
check.append(ethHeader->dst_mac.mac5);
check.append(ethHeader->dst_mac.mac6);//'check' contains the current MAC of the packet
if(wantedMac.contains(check.toAscii().toHex())){ //if 'check' contains the MAC I was looking for
/*
* Create fake IP header and put UDP header
* and payload in place
* --> how to do this for all wanted packets?
*/
pcap_dump((u_char *)pdumper, header, pkt_data); //write changed packet to file
}
else{
//delete the packet --> how?
}
}
}
pcap_close(pd);
pcap_dump_close(pdumper);
}
I have had a look at this, and it helped, but just up to this point. My code is all I have so far.
Edit: As a first step, I would also be happy if I were able to save the edited packets in a second file, not in the file the packets come from. But how to edit them?
Ok, I figured out something by myself. It might not be the most elegant solution, but it works.
QString string;
QStringList mac;
int result=0;
bool ok;
QChar d
string=mac[0];//first part of mac address to string
for(int i=0; i<string.length();i++){//string to ascii hex and int
d=string.toUInt(&ok,16);
result=d.unicode();
}
ethHeader->dst_mac.macPart1=result;//allocate, go on for next part of macaddress

Resources